洛谷 P4706 取石子 解题报告
P4706 取石子
題目描述
現在 Yopilla 和 yww 要開始玩游戲!
他們在一條直線上標記了 \(n\) 個點,從左往右依次標號為 \(1, 2, ..., n\) 。然后在每個點上放置一些棋子,其中第 \(i\) 個點放置了 \(a_i\) 個棋子。接下來,從 Yopilla 開始操作,雙方輪流操作,誰不能操作誰輸。每次的操作是:當前操作方選定一個有棋子的點 \(x\) ,然后選擇至少一個點 \(x\) 上的棋子,然后把這些棋子全都移動到點 \(x / prime\)上,其中 \(prime\) 是一個質數,且 \(prime \mid x\) 。
Yopilla 最初一次操作的策略是隨機的:隨機找到一個有棋子的點 \(x\) ,隨機選擇正整數個棋子 \(y\) ,隨機轉移到一個能轉移到的點 \(z\)。所有棋子可以看作是一樣的,換句話說:兩種操作不同,當且僅當三元組 \((x, y, z)\) 不同。之后雙方都按照最優策略來操作。
Yopilla 想要預測,他能夠獲勝的概率是多少,答案對 $998244353$3 取模。
輸入輸出格式
輸入格式:
第一行一個數 \(n\) 。
第二行 \(n\) 個數 \(a_1, a_2, ..., a_n\) 。
輸出格式:
輸出 \(m\) 行,表示 Yopilla 能夠獲勝的概率對 \(998244353\) 取模。
說明
對于 \(20 \%\) 的數據,只有一個石子。
對于 \(100 \%\) 的數據,\(1 \le n \le {10} ^ 6, 0 \le a_i \le {10} ^ 9\),保證至少有一個不在一號點的石子。
太神仙了...
如果把圖建出來,我們可以按照每個數的冪的和的奇偶性構造二分圖(1為偶),然后就是一個階梯\(Nim\)問題
link
然后我們篩一下每個數的質因子個數順便分層,然后統計一下奇層的\(SG\)
總情況很好算
然后枚舉一下隨機操作對\(SG\)函數的影響
具體的,枚舉每一個奇層的點,然后發現這個點要變成\(SG \ xor \ a_i\)才能使對面必敗,然后討論一下這個值是給出去還是由別人給的情況。
最后算一下概率就可以了。
Code:
#include <cstdio> const int N=1e6+1; int pri[N],ispri[N],is[N],num[N],cnt; int n,a[N],SG; #define ll long long const ll mod=998244353; ll win,sum; ll qp(ll d,ll k){ll f=1;while(k){if(k&1)f=f*d%mod;d=d*d%mod,k>>=1;}return f;} void init() {for(int i=2;i<=n;i++){if(!ispri[i]){pri[++cnt]=i;num[i]=is[i]=1;}for(int j=1;j<=cnt&&i*pri[j]<=n;j++){int x=i*pri[j];ispri[x]=1;is[x]=is[i]^1;if(i%pri[j]) num[x]=num[i]+1;else {num[x]=num[i];break;}}} } int main() {scanf("%d",&n);init();for(int i=1;i<=n;i++){scanf("%d",a+i);if(is[i]) SG^=a[i];(sum+=1ll*a[i]*num[i])%=mod;}for(int i=1;i<=n;i++)if(is[i]){int to=SG^a[i];if(a[i]>to)(win+=num[i])%=mod;else if(a[i]<to)for(int j=1;j<=cnt&&pri[j]*i<=n;j++)win+=a[i*pri[j]]>=to-a[i];}printf("%lld\n",win*qp(sum,mod-2)%mod);return 0; }2018.12.18
轉載于:https://www.cnblogs.com/butterflydew/p/10140080.html
總結
以上是生活随笔為你收集整理的洛谷 P4706 取石子 解题报告的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: bzoj 1004: [HNOI2008
- 下一篇: ConcurrentHashMap源码解