Fortnight Round 1 题解
T1
题意
有
你需要进行
给出一个参数
输出是否能完成所有操作。
数据范围:
题解
by XiaoShanYunPan。
首先要把
感性上,我们觉得限制非常松,应该大部分情况都是有解的。
思考一下会发现,如果
而如果
剩下的问题是如果
此时我们有结论:如果
这个东西无解是显然的,我们的问题在于为什么剩下的情况一定有解。
首先,如果
接下来每次均对第一步未操作的那个位置操作,上述两个不同的状态一定只能有一个恰好到达
为什么?注意到如果第一个状态经过若干次操作后得到
那么接下来考虑
直接根据上述讨论判断即可。
T2
题意
对于长度为
现在给定
答案对
数据范围:
题解
by XiaoShanYunPan。
考虑一个弱化问题,如果只有
下面是这个问题的完整描述:
对于长度为
m 的二进制串A 和长度为m 的排列P ,我们定义g(A,P)_i=A_{P_i} 。现在给定
n 组串S_i,T_i ,求有多少种可能的P ,使得T_i=g(S_i,P) 。
我们发现,如果
将其横竖倒置,令
使用桶记录
然后考虑加上
于是本题做完了,时间复杂度
如果
另外还要注意判断无解和
一个有趣的事实是我们特别在最后一个子任务中没有放入
T3
题意
求
数据范围:
题解
by ECEG。
特别鸣谢 TabEsc。
先将
注意到:
注意到当
这启发我们将
不妨设
先考虑自身段贡献,因为前
接下来考虑第
注意到对于一个
但是这里,第
接下来就很简单了,用一个后缀和,就不需要枚举
其他
被猫猫偷走的提示是 猫猫好坏,狠狠地敲猫猫的头喵喵喵喵喵!
代码
const int maxn=1e6+4,mod=998244353;int n,inv5,inv2,inv3,inv30,suf[maxn],pw[maxn],ans;char a[maxn],op[maxn];
int fast_pow(int x,int y,int res=1){for(;y;y>>=1,x=x*1ll*x%mod)if(y&1)res=res*1ll*x%mod;return res;}
int pw5(int x){return x*1ll*x%mod*x%mod*x%mod*x%mod*inv5%mod;}
int pw4(int x){return x*1ll*x%mod*x%mod*x%mod*inv2%mod;}
int pw3(int x){return x*1ll*x%mod*x%mod*inv3%mod;}
int sum(int x){return (((pw5(x)+pw4(x))%mod+pw3(x))%mod+mod-x*1ll*inv30%mod)%mod;}
signed main(){
read(n);scanf("%s",op);
inv5=fast_pow(5,mod-2);inv2=fast_pow(2,mod-2);inv3=fast_pow(3,mod-2);inv30=fast_pow(30,mod-2);
int tmp=0;pw[0]=1;
for(int i=0;i<n;++i)tmp+=(op[i]=='0');
if(!tmp){
n++;a[0]='1';
for(int i=1;i<n;++i)a[i]='0';
}
else{
for(int i=0;i<n;++i)a[i]=op[i];
a[n-1]++;
for(int i=n-1;i>=0;--i){
if(a[i]>'1')a[i]='0',a[i-1]++;
else break;
}
}
for(int i=1;i<=n+2;++i)pw[i]=pw[i-1]*2ll%mod;
for(int i=n-1;i>=0;--i){
suf[i]=suf[i+1];
if(a[i]=='1'){
(ans+=(sum(pw[n-i]-1)-sum(pw[n-i-1]-1)+mod)%mod*1ll*suf[i]%mod)%=mod;
(ans+=sum(pw[n-i-1]-1)*1ll*pw[n-i-1]%mod)%=mod;
(suf[i]+=pw[n-i])%=mod;
}
}
write(ans);
return 0;
}
T4
题意
求有多少个长度为
答案对
数据范围:
题解
by Locix_Elaina_Celome,略有修改。
1\le k\le 2n\le 10
直接枚举全排列并检验。
时间复杂度
1\le k\le 2n\le 18
枚举每个数放在左边还是右边,然后检验。最后乘上一个排列数。
时间复杂度
1\le k\le 2n\le 50
发现这个问题可以转化为:把
因为
考虑一个 dp,设一个
但是发现这样复杂度
发现为
那么就可以把上面的 dp 状态中的
if(j)dp[i][j][x*i%k][y]=(dp[i][j][x*i%k][y]+dp[i-1][j-1][x][y])%P;
if(j<i)dp[i][j][x][y*i%k]=(dp[i][j][x][y*i%k]+dp[i-1][j][x][y])%P;
答案即为
时间复杂度
1\le k\le 2n\le 300
观察上面的dp,模意义不太帅气,因为有
还是从最原始的
发现可以将
于是就把上面的对
因为
1\le k\le 2n\le 2000
注意到
于是其中一个集合的乘积和
时间复杂度
更强一些
本题也许可以用生成函数等进一步优化,出题团队太懒了没搞,有大佬搞出来了踹我们一脚。