『模拟赛』暑假集训CSP提高模拟24

Rank

G

image

A. 与和

原[ABC238D] AND and SUM

签。不过因为忘了 and 是啥被控 40min 还是太蒻了

\(a\) 进行二进制拆分,1 是 \(x\)\(y\) 共有的,直接乘 2 计入和内,0 说明二者中最多出现一个 1,倍增思想,倒序枚举,若计入和后不超过 \(s\) 则计入,否则跳过,最终比较和与 \(s\) 的大小关系即可。

点击查看代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

const int Ratio=0;
ll a,b,x,y,sum;
int num[105],nm;
namespace Wisadel
{
    ll Wqp(ll x,int y)
    {
        ll res=1;
        while(y){if(y&1) res=res*x;x=x*x;y>>=1;}
        return res;
    }
    short main()
    {
        freopen("and.in","r",stdin),freopen("and.out","w",stdout);
        int T;scanf("%d",&T);
        while(T--)
        {
            scanf("%lld%lld",&a,&b);memset(num,0,sizeof num);sum=0,nm=0;
            while(a) num[nm++]=a&1,a>>=1;
            for(int i=0;i<nm;i++)
                if(num[i]) sum+=2*Wqp(2,i);
            for(int i=60;i>=0;i--)
            {
                if(num[i]) continue;
                if(Wqp(2,i)+sum<=b) sum+=Wqp(2,i);
            }
            if(sum==b) printf("Yes\n");
            else printf("No\n");
        }
        return Ratio;
    }
}
int main(){return Wisadel::main();}

B. 函数

原[ABC366F] Maximum Composition

\(\times 2\,\)不过没签上

一个显然的选择策略,设 \(f_1\left(x\right)=A_1x+B_1\)\(f_2\left(x\right)=A_2x+B_2\),那么若 \(f_1\left(f_2\left(x\right)\right)\lt f_2\left(f_1\left(x\right)\right)\),则化简后可得:

\[A_1B_2+B_1\lt A_2B_1+B_2 \]

以此类推,可以得到一个结论:越大的 \(B\) 越靠前值越大;越大的 \(A\) 越靠后值越大。但二者是并列关系,于是就蒙了,所以就胡乱打了个两种情况各取最优的 \(k\) 个然后枚举一遍,结果小点全挂喜提 69pts。

正解是 dp,我们按照上面的原则排序,定义 \(f_{i,j}\) 为到第 \(i\) 位选了 \(j\) 个的最大值,那么状态转移方程显然为:

\[f_{i,j}=\max_{j=0}^k f_{i-1,j-1}\times A_i+B_i\left(j\neq 0\right) \]

同时,记得赋初始值 \(f_{i,j}=f_{i-1,j}\) 以及边界 \(f_{0,0}=1\)

时间复杂度 \(\mathcal{O(n^2)}\)

点击查看代码
#include<bits/stdc++.h>
#define fo(x,y,z) for(register int (x)=(y);(x)<=(z);(x)++)
using namespace std;
typedef long long ll;
inline int qr()
{
	char ch=getchar();int x=0,f=1;
	for(;ch<'0'||ch>'9';ch=getchar()) if(ch=='-') f=-1;
	for(;ch>='0'&&ch<='9';ch=getchar()) x=(x<<3)+(x<<1)+(ch^48);
	return x*f;
}
#define qr qr()
const int Ratio=0;
const int N=2e5+5;
int n,k;
struct rmm
{
    int a,b;
    bool operator<(const rmm &A)const{return a*A.b+b<A.a*b+A.b;}
}a[N];
ll f[N][15];
namespace Wisadel
{
    short main()
    {
        freopen("func.in","r",stdin),freopen("func.out","w",stdout);
        n=qr,k=qr;f[0][0]=1;
        fo(i,1,n) a[i].a=qr,a[i].b=qr;
        sort(a+1,a+1+n);
        fo(i,1,n) fo(j,0,k)
        {
            f[i][j]=f[i-1][j];
            if(j) f[i][j]=max(f[i][j],f[i-1][j-1]*a[i].a+a[i].b);
        }
        printf("%lld\n",f[n][k]);
        return Ratio;
    }
}
int main(){return Wisadel::main();}

C. 袋鼠

原[CEOI2016] kangaroo

一眼简单,再一眼没思路。

赛时打了暴搜,\(n\ge 15\) 就寄了,然后打表一共 12pts。

正解是很神的插入法 dp,首先将我们跳转的顺序转化成序列,那么就成为了求序列以 \(s\) 开头以 \(t\) 结尾的序列合法的个数。状态定义为 \(f_{i,j}\) 表示已经插入了前 \(i\) 个数并且当前序列被分成 \(j\) 段的个数,那么转移时只有三种情况:

  • 新开一个连续段,此时 \(i\) 大于前面任何数,所以可以随便插,方案数为 \(j\);但开头结尾已经确定,所以 \(i\gt s\)\(i\gt t\)\(j\) 分别要减一;状态转移方程为:

\[f_{i,j}+=\left(j-\left[i\gt s\right]-\left[i\gt t\right]\right)\times f_{i-1,j-1} \]

  • 新加入的 \(i\) 将两个连续段连接起来,同理可以随便插,方案数为 \(j\),状态转移方程为:

\[f_{i,j}+=j\times f_{i-1,j+1} \]

  • 新加入的 \(i\)\(s\)\(t\),此时只有一种情况即将其置于头或尾,可以单独成段或连上相邻的一段,转移方程为:

\[f_{i,j}=f_{i-1,j}+f_{i-1,j-1} \]

时间复杂度 \(\mathcal{O(n^2)}\)

点击查看代码
#include<bits/stdc++.h>
#define fo(x,y,z) for(register int (x)=(y);(x)<=(z);(x)++)
typedef long long ll;

const int Ratio=0;
const int N=2e3+5;
const int mod=1e9+7;
int n,st,ed,ans;
ll f[N][N];
namespace Wisadel
{
    short main()
    {
        freopen("kang.in","r",stdin),freopen("kang.out","w",stdout);
        scanf("%d%d%d",&n,&st,&ed);f[1][1]=1;
        fo(i,2,n) fo(j,1,i)
        {
            if(i!=st&&i!=ed) f[i][j]=(j*f[i-1][j+1]%mod+(j-(i>st)-(i>ed))*f[i-1][j-1]%mod)%mod;
            else f[i][j]=f[i-1][j-1]+f[i-1][j];
        }
        printf("%lld\n",f[n][1]);
        return Ratio;
    }
}
int main(){return Wisadel::main();}

D. 最短路

原[CF464E] The Classic Problem

赫拉格老爷子你说你游戏里公招控我就算了到题面上还这么难

还有,

为什么没有棘刺的题?为什么没有棘刺的题?为什么没有棘刺的题?为什么没有棘刺的题?为什么没有棘刺的题?为什么没有棘刺的题?为什么没有棘刺的题?为什么没有棘刺的题?为什么没有棘刺的题?为什么没有棘刺的题?

快出道棘刺的题啊啊!快出道棘刺的题啊啊!快出道棘刺的题啊啊!快出道棘刺的题啊啊!快出道棘刺的题啊啊!快出道棘刺的题啊啊!快出道棘刺的题啊啊!快出道棘刺的题啊啊!快出道棘刺的题啊啊!快出道棘刺的题啊啊!

赛时想了有正确性的错解,由于边权都是 \(2\) 的幂,因此我们只要记下最短路边权的所有指数就可以正常地操作更新了,不过实现要依靠优先队列所以时间上直接 T 飞了啊,还没有图小一点的测试点所以直接保龄,还不如暴力硬上 Dijkstra 能拿 8pts。

正解需要高精度,哈希,主席树,感觉这实现起来比黑题还黑题。

也许锣鼓的运势影响心情?今天大凶,前几天都大吉。

前三道都不难,感觉如果出到三场模拟赛的 T1 就都能切吧?

还有就是没思路了就考虑 dp,大概率是这样的,如果状态设计差不多就能拿不少分。

一些

蜜马我昵称


完结撒花~

image

posted @ 2024-08-19 19:10  DrRatio  阅读(36)  评论(0编辑  收藏  举报