bzoj 4872 [Shoi2017]分手是祝願
阿新 • • 發佈:2018-07-27
idt width char code lan int return stdin 是我
題面
https://www.lydsy.com/JudgeOnline/problem.php?id=4872
題解
首先解法是唯一的
所以我們算出最少要按幾次 然後如果<=k那麽就這麽按 獲得80分(真多啊...)
然後我們令f[i]表示當前離結果還有i步,我們要得到結果的期望步數
又因為f[k]=k 所以我們可以解出所有的f
f[最少要按幾次]*n!就是答案
我們可以遞推 設f[i]=Af[i+1]+B 這樣我們從k+1跑到n 每一個i的A,B都可以求出來 這樣我們就解出了f[n]
然後記錄下每一個i對應的A,B 逆著推回去 就能解出f[最少要按幾次]
但是由於不知名問題 我的這個寫法只獲得95分 可能在取模和求逆元的過程中出現了問題
於是我因為這種方法不是正解(失去調試的耐心)而放棄了這種做法
然後百度一下
差分!!!
考慮差分f,或者說g[i]表示i到i-1步的期望步數
這樣得到
g[i]=((n-i)(g[i]+1)+n)/i
然後答案就是(g[m]+...+g[k+1]+k)*n!
Code
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 5 ll read(){ 6 ll x=0,f=1;char c=getchar(); 7 while(c<‘0‘ || c>‘95分的代碼9‘){if(c==‘-‘)f=-1;c=getchar();} 8 while(c>=‘0‘ && c<=‘9‘){x=x*10+c-‘0‘;c=getchar();} 9 return x*f; 10 } 11 12 const int mod=100003; 13 int n,k; 14 int a[100100]; 15 16 int ksm(int x,int p){ 17 int ret=1; 18 while(p){ 19 if(p&1) ret=ret*1ll*x%mod; 20 x=x*1ll*x%mod;21 p=p>>1; 22 } 23 return ret; 24 } 25 26 int p[100100]; 27 int recA[100100],recB[100100]; 28 int main(){ 29 #ifdef LZT 30 freopen("in","r",stdin); 31 #endif 32 n=read(),k=read(); 33 for(int i=1;i<=n;i++) 34 a[i]=read(); 35 int m=0; 36 for(int i=n;i>=1;i--){ 37 if(a[i]){ 38 m++; 39 for(int j=1;j*j<=i;j++){ 40 if(i%j!=0) continue; 41 a[j]^=1; 42 if(j*j!=i) a[i/j]^=1; 43 } 44 } 45 } 46 if(k>=m){ 47 for(int i=1;i<=n;i++) 48 m=m*1ll*i%mod; 49 printf("%d\n",m); 50 return 0; 51 } 52 int t=ksm(n,mod-2); 53 //cout<<t<<endl; 54 p[k]=k; 55 int A=0,B=0; 56 for(int x=k+1;x<=n;x++){ 57 if(x==k+1){ 58 A=t*1ll*(n-x)%mod; 59 B=(t*1ll*x%mod*p[x-1]%mod+1)%mod; 60 recA[x]=A; 61 recB[x]=B; 62 //cout<<A<<‘ ‘<<B<<endl; 63 continue; 64 } 65 int nw=t*1ll*x%mod*A%mod; 66 nw=(1-nw+mod)%mod; 67 nw=ksm(nw,mod-2); 68 A=nw*1ll*t%mod*(n-x)%mod; 69 B=nw*1ll*(t*1ll*x%mod*B%mod+1)%mod; 70 recA[x]=A; 71 recB[x]=B; 72 //cout<<A<<‘ ‘<<B<<endl; 73 } 74 int val=B; 75 for(int i=n-1;i>=m;i--) 76 val=(recA[i]*1ll*val%mod+recB[i]%mod)%mod; 77 for(int i=1;i<=n;i++) 78 val=val*1ll*i%mod; 79 printf("%d\n",val); 80 return 0; 81 }
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 5 ll read(){ 6 ll x=0,f=1;char c=getchar(); 7 while(c<‘0‘ || c>‘9‘){if(c==‘-‘)f=-1;c=getchar();} 8 while(c>=‘0‘ && c<=‘9‘){x=x*10+c-‘0‘;c=getchar();} 9 return x*f; 10 } 11 12 const int mod=100003; 13 int n,k; 14 int a[100100]; 15 16 int ksm(int x,int p){ 17 int ret=1; 18 while(p){ 19 if(p&1) ret=ret*1ll*x%mod; 20 x=x*1ll*x%mod; 21 p=p>>1; 22 } 23 return ret; 24 } 25 26 int p[100100]; 27 //int recA[100100],recB[100100]; 28 int main(){ 29 #ifdef LZT 30 freopen("in","r",stdin); 31 #endif 32 n=read(),k=read(); 33 for(int i=1;i<=n;i++) 34 a[i]=read(); 35 int m=0; 36 for(int i=n;i>=1;i--){ 37 if(a[i]){ 38 m++; 39 for(int j=1;j*j<=i;j++){ 40 if(i%j!=0) continue; 41 a[j]^=1; 42 if(j*j!=i) a[i/j]^=1; 43 } 44 } 45 } 46 if(k>=m){ 47 for(int i=1;i<=n;i++) 48 m=m*1ll*i%mod; 49 printf("%d\n",m); 50 return 0; 51 } 52 int t=ksm(n,mod-2); 53 /* 54 //cout<<t<<endl; 55 p[k]=k; 56 int A=0,B=0; 57 for(int x=k+1;x<=n;x++){ 58 if(x==k+1){ 59 A=t*1ll*(n-x)%mod; 60 B=(t*1ll*x%mod*p[x-1]%mod+1)%mod; 61 recA[x]=A; 62 recB[x]=B; 63 //cout<<A<<‘ ‘<<B<<endl; 64 continue; 65 } 66 int nw=t*1ll*x%mod*A%mod; 67 nw=(1-nw+mod)%mod; 68 nw=ksm(nw,mod-2); 69 A=nw*1ll*t%mod*(n-x)%mod; 70 B=nw*1ll*(t*1ll*x%mod*B%mod+1)%mod; 71 recA[x]=A; 72 recB[x]=B; 73 //cout<<A<<‘ ‘<<B<<endl; 74 } 75 int val=B; 76 for(int i=n-1;i>=m;i--) 77 val=(recA[i]*1ll*val%mod+recB[i]%mod)%mod; 78 for(int i=1;i<=n;i++) 79 val=val*1ll*i%mod; 80 printf("%d\n",val);*/ 81 p[n]=1; 82 for(int i=n-1;i>k;i--) 83 p[i]=((n-i)*1ll*p[i+1]%mod+n)%mod*1ll*ksm(i,mod-2)%mod; 84 int val=0; 85 for(int i=m;i>k;i--) 86 val=(val+p[i])%mod; 87 val=val+k; 88 for(int i=1;i<=n;i++) 89 val=val*1ll*i%mod; 90 printf("%d\n",val); 91 return 0; 92 }100分的代碼
Review
動機?
到95分為止都是自己想到的 也不是很難想
然後差分... 這個怎麽想到的我也不是很清楚
(如果遞推式沒法推就差分一下?)
bzoj 4872 [Shoi2017]分手是祝願