洛谷比賽-P5011 水の造題-題解
阿新 • • 發佈:2018-12-19
題目地址與題意見連結
暴力就是 吧,不過 非常之大,有 (高精可怕.jpg)
但是我們發現,對於求期望,那麼就是概率 權值,所以我們可以先求出每種動作的貢獻:
每種動作出現在某個位置的概率為 ,貢獻為它的 ,總共有 個可以出現的位置,所以貢獻為
接下來就是組合技的多的貢獻,每個組合技還會再貢獻一次,所以我們這樣來看:
每個組合技出現的概率為 ,有 個可以出現的位置,每一種的貢獻為 ,所以總貢獻為
那麼我們
的算一下就好啦,關於取模除法我們用費馬小定理逆元就可以了,因為
是個非常神奇且有巨大意義的質數,讀入
時直接取模就好啦。
程式碼:
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const int M=1e6+10;
const ll Mod=19491001;
char s[M];
ll k,A[M],n,w;
ll inv_k,inv_k2;
void readin(){
scanf("%s",s);
int len=strlen(s);
for(int i=0;i<len;i++){
n=(n*10ll%Mod+(s[i]&15))%Mod;
} w=(n-1+Mod)%Mod;
}
ll Sqr(ll a){return a*a%Mod;}
ll fpow(ll a,ll b){
ll ans=1;
for(;b;b>>=1,a=(a*a)%Mod)if(b&1)ans=(ans*a)%Mod;
return ans;
}
ll ans,sum1,sum2;
int main(){
readin();
scanf("%lld",&k);
for(int i=0;i<k;i++){
scanf("%lld",&A[i]);
sum1=(sum1+A[i])%Mod;
if(i)sum2=(sum2+(A[i-1]+A[i])%Mod)%Mod;
} sum2=(sum2+(A[0]+A[k-1])%Mod)%Mod;
inv_k=fpow(k,Mod-2);
inv_k2=(Sqr(inv_k)%Mod*w)%Mod;inv_k=(inv_k*n)%Mod;
ans=(sum1*inv_k%Mod+sum2*inv_k2%Mod)%Mod;
printf("%lld\n",ans);
return 0;
}
下面還有一種解法,由 |Orz|提供:
我們先不考慮開頭結尾,那麼每個數都有前後:
我們考慮,對於一個位置的動作,它前後都不是組合技,那麼只會貢獻一次,那麼前面不是和它組合的概率為 ,後面不是和它組合的概率為 ,然後當前選這個的概率為 ,有 個位置可以這樣選,那麼貢獻為
對於可以形成組合技的(這裡只考慮組成一個),那麼就是後面和它組合,前面不組合;或者前面組合,後面不組合。那麼貢獻就為 (這時 要算兩次貢獻,同樣還是有 個可以的位置)
對於前後都可以組合的,概率為 ,所以貢獻為