1 条题解
-
0
自动搬运
来自洛谷,原作者为

cyffff
Not yet for the story on the last page, it's not the end.搬运于
2025-08-24 22:02:48,当前版本为作者最后更新于2021-07-06 12:40:45,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
题意
有 堆棋子,第 堆有 个棋子,定义一次操作为选择第 堆棋子中任意个棋子转移到第 堆中。其中 是 的质因数。
两人轮流操作,不能操作者输。若先手第一步随机操作一步,问先手获胜的概率。对 取模。
。
思路
前置知识:阶梯 博弈
描述:有 堆棋子,第 堆有 个棋子,定义一次操作为选择第 堆棋子中任意个棋子转移到第 堆中。两人轮流操作,不能操作者输。求先手是否有必胜策略。
可以得到,此时的 函数 $f(x)=a_1\text{ xor }a_3\text{ xor }a_5\text{ xor }\cdots\text{ xor } a_{n-[2|n]}$,此处不多作介绍,可以参考这份讲解。
设 的标准分解式为 ,定义 。这个可以线性筛出来。
我们发现,如果以 的奇偶性分层连边,则问题转化为在奇偶层之间移动棋子的阶梯 博弈。
首先我们知道先手第一步走的方式有 种。
然后来判断有多少种合法方法。
枚举奇层的所有 ,若操作后 变为 ,则先手能胜利,则定义 ,则 变为 后 变为 。
然后对于 和 的大小分类讨论。
- ,此时 ,若对 做出改动,则 定不等于 ,故此类无贡献;
- ,考虑将 处的 颗棋子转移至偶层,则对答案作出 的贡献;
- ,考虑枚举 ,将偶层 处的 颗棋子转移至奇层 处,则对答案作出 的贡献。
最后除一下得出概率就行了!
代码:
#include<bits/stdc++.h> using namespace std; #define ll long long namespace IO{//by cyffff } const int N=1e6+10,mod=998244353; int n,a[N],rnd,sol; bitset<N>p; int pri[N],cnt,sum[N]; bool odd[N]; /* sum->质因数个数 odd->指数和是否为奇 */ inline int qpow(int x,int y){ int res=1; while(y){ if(y&1) res=1ll*res*x%mod; x=1ll*x*x%mod; y>>=1; } return res; } inline void sieve(int n){ p[1]=1; for(int i=2;i<=n;i++){ if(!p[i]){ pri[++cnt]=i; sum[i]=odd[i]=1; } for(int j=1;j<=cnt&&i*pri[j]<=n;j++){ p[i*pri[j]]=1; odd[i*pri[j]]=odd[i]^1; if(i%pri[j]==0) { sum[i*pri[j]]=sum[i]; break; } sum[i*pri[j]]=sum[i]+1; } } } int SG; int main(){ n=read(); sieve(n); for(int i=1;i<=n;i++){ a[i]=read(); if(odd[i]) SG^=a[i]; rnd=(rnd+1ll*a[i]*sum[i])%mod; } for(int i=1;i<=n;i++){ if(odd[i]){ int need=SG^a[i]; if(need==a[i]) continue; if(need<a[i]) sol=(sol+sum[i])%mod; else{ for(int j=1;j<=cnt&&pri[j]*i<=n;j++){ if(a[i*pri[j]]>=need-a[i]) sol++; } sol-=sol>=mod?mod:0; } } } write(1ll*sol*qpow(rnd,mod-2)%mod); flush(); }再见 qwq~
- 1
信息
- ID
- 3614
- 时间
- 1000ms
- 内存
- 125MiB
- 难度
- 6
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者