CSP 提高组模拟6 题解

T1 花间叔祖

其实是化简数组。赛时94pts,因为少加了abs挂6pts。

题目描述

给你一个序列 A,选择一个数 p2,使得整个序列 modp 后数字的种类最少。序列长度满足 2N2×105,序列中的数值满足 0Ai109

部分分

这题拿部分分的就是纯挂分。

正解

思路

首先来个小结论:若 ab(modp),则 p 的取值为 abk, k(ab)

证明如下:

因为 ab(modp),所以amodp=bmodp,即存在两个自然数 x,y 满足ax×p=by×p

移项,得 ab=(xy)×p

xy 除到等式左边,可得 abxy=p

由于 p 是正整数,所以 xyab,证毕。

然后来看题目,发现输出的结果只能是 12,因为一个序列 mod2 最多只可能会出现两种数字,即 01,如果答案是 1,那么这个序列一定满足存在一个 p2,使得 A 中的每一项 modp 结果相同。根据我们在最开始推导的柿子,p 可以被表示为 Ai 递差的 gcd。求出来判断是不是 1 即可。

代码

#include<bits/stdc++.h>
using namespace std;
#define il inline
#define ri register int
#define inf 0x3f3f3f3f
int a,b[200002],re;
int main()
{
scanf("%d",&a);
for(ri i=1;i<=a;i++)
{
scanf("%d",&b[i]);
}
for(ri i=2;i<=a;i++)
{
re=__gcd(abs(b[i]-b[i-1]),re);//细节:要么sort一遍,要么+abs
if(re==1)
{
puts("2");
exit(0);
}
}
puts("1");
return 0;
}
/*
*/

T2 合并r

赛时60pts,但这题暴力的极限是75pts。数组开小了挂15pts

题目描述

给你两个整数 nk,规定满足条件的实数为 12ii 为自然数,求出用 n 个满足条件的实数拼出 k 的所有不同方案数,答案对 998244353 取模。

部分分

10pts

特判 n=1,输出 1

?pts

暴搜,反正我没打。

75pts

考虑的k=2时的值,对于1来说是两个,对12来说就是四个,对14来说是八个……以此类推,设计记搜,dp[i][j]表示i个数相对于它本身空间为j时的情况,不难得出状态转移方程:dp[i][j]=k=0idp[ik][j×2]
加点边界判定,数组开大,75pts到手。

点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define il inline
#define ri register int
#define inf 0x3f3f3f3f
const int mod=998244353;
int a,b;
long long dp[5005][5005];
long long dfs_pro(int x,int y)
{
if(y>x||y==0)
{
return 0;
}
if(x==y)
{
return 1;
}
if(dp[x][y]>0)
{
return dp[x][y];
}
long long rn=0;
for(ri i=0;i<=y;i++)
{
rn+=dfs_pro(x-i,(y-i)<<1);
rn%=mod;
}
dp[x][y]=rn;
return dp[x][y];
}
int main()
{
scanf("%d%d",&a,&b);
printf("%lld",dfs_pro(a,b));
return 0;
}
/*
*/

正解

思路

考虑如果当前凑出了 k,那么把这之中的所有之都 ÷2,就可以得到 k2。这样的话,我们找到的所有情况中的数值都是一点一点 ÷2操作出来的,初始的值就应该是 1,所有添加值不是 1 的情况都可以被 ÷2 的情况覆盖,只需考虑 +1÷2 即可。

代码

#include<bits/stdc++.h>
using namespace std;
#define il inline
#define ri register int
#define inf 0x3f3f3f3f
const int mod=998244353;
int a,b;
long long dp[5005][5005];
int main()
{
scanf("%d%d",&a,&b);
dp[0][0]=1;//初始化
for(ri i=1;i<=a;i++)
{
for(ri j=i;j>=1;j--)//由于需要调用j*2的值,所以要倒序
{
dp[i][j]=dp[i-1][j-1];
if((j<<1)<=i)
{
dp[i][j]+=dp[i][j<<1];
}
dp[i][j]%=mod;
}
}
printf("%lld",dp[a][b]);
return 0;
}
/*
*/
posted @   一位很会的教授er~  阅读(40)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示