日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

[集训队作业2018]uoj 449 喂鸽子 - min-max容斥 - dp - NTT

發布時間:2023/12/20 编程问答 50 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [集训队作业2018]uoj 449 喂鸽子 - min-max容斥 - dp - NTT 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題目大意:有n個數字一開始全0,每次隨機一個數字++,問期望多少步后第一次有個位置的數字的值是k。n≤50,k≤1000n\le50,k\le1000n50,k1000。
題解:
顯然k=1是個min-max容斥。因此min-max容斥。假設枚舉的集合大小是aaa。
一開始場上的做法是,期望轉為∑i≥1P(ans≥i)\sum_{i\ge1}P(ans\ge i)i1?P(ansi),然后P(ans≥i)P(ans\ge i)P(ansi)就是說到i?1i-1i?1的時候還沒好的概率,然后再枚舉這i-1次操作中多少次落在左半邊,整理式子后發現有個組合數數列點積等比數列的求和,總之推導一波后發現要計算大小為a的集合i步后不存在>=k的數值的方案數,發現這玩意只能n2k2n^2k^2n2k2dp,但是是卷積,場上寫個NTT過了。
另一種做法是直接枚舉:∑i≥1P(ans=i)i\sum_{i\ge 1}P(ans=i)ii1?P(ans=i)i,然后還是枚舉左邊的次數j,右邊還是組合數數列點積等比數列的求和(其實算出來就是na\frac naan?),推導一下發現要算大小為a的集合i步后恰好有個位置是k的方案數,這個就用欽定某個數第i步是出現恰好k次的總方案數減去不合法的位置。后者用個前綴和即可。其實就是推式子很麻煩,但直接冷靜思考一波就是a的答案乘以na\frac naan?的比率即可。

#include<bits/stdc++.h> #define rep(i,a,b) for(int i=a;i<=b;i++) #define Rep(i,v) rep(i,0,(int)v.size()-1) #define lint long long #define p 998244353 #define ull unsigned lint #define db long double #define pb push_back #define mp make_pair #define fir first #define sec second #define gc getchar() #define debug(x) cerr<<#x<<"="<<x #define sp <<" " #define ln <<endl using namespace std; typedef pair<int,int> pii; typedef set<int>::iterator sit; inline int inn() {int x,ch;while((ch=gc)<'0'||ch>'9');x=ch^'0';while((ch=gc)>='0'&&ch<='9')x=(x<<1)+(x<<3)+(ch^'0');return x; } const int N=52,K=1002; int f[2][N*K],fac[N*K],facinv[N*K],inv[N*K],mi1[N*K],mi2[N*K]; inline int fast_pow(int x,int k,int ans=1) { for(;k;k>>=1,x=(lint)x*x%p) (k&1)?ans=(lint)ans*x%p:0;return ans; } inline int C(int n,int m) { return assert(n>=m&&m>=0),(lint)fac[n]*facinv[m]%p*facinv[n-m]%p; } inline int prelude(int n) {rep(i,fac[0]=1,n) fac[i]=(lint)i*fac[i-1]%p;facinv[n]=fast_pow(fac[n],p-2);for(int i=n-1;i>=0;i--) facinv[i]=(i+1ll)*facinv[i+1]%p;rep(i,1,n) inv[i]=(lint)fac[i-1]*facinv[i]%p;return 0; } int main() {int n=inn(),k=inn(),ans=0;prelude(n*k);rep(i,1,n){int *now=f[i&1],*pre=f[(i-1)&1],s=0;rep(j,k,(i-1)*(k-1)+1) pre[j]=(pre[j]+(i-1ll)*pre[j-1])%p;rep(j,mi1[0]=1,i*(k-1)+1) mi1[j]=mi1[j-1]*(i-1ll)%p;rep(j,mi2[0]=1,i*(k-1)+2) mi2[j]=(lint)mi2[j-1]*inv[i]%p;rep(j,k,i*(k-1)+1)now[j]=(lint)i*C(j-1,k-1)%p*(mi1[j-k]-pre[j-k])%p,(now[j]<0?now[j]+=p:0),s=(s+(lint)now[j]*j%p*mi2[j+1])%p;if(i&1) ans=(ans+(lint)C(n,i)*s)%p;else ans=(ans-(lint)C(n,i)*s)%p,(ans<0?ans+=p:0);}return !printf("%lld\n",(lint)ans*n%p); } #include<bits/stdc++.h> #define rep(i,a,b) for(int i=a;i<=b;i++) #define Rep(i,v) rep(i,0,(int)v.size()-1) #define lint long long #define p 998244353 #define ull unsigned lint #define db long double #define pb push_back #define mp make_pair #define fir first #define sec second #define gc getchar() #define debug(x) cerr<<#x<<"="<<x #define sp <<" " #define ln <<endl using namespace std; typedef pair<int,int> pii; typedef set<int>::iterator sit; inline int inn() {int x,ch;while((ch=gc)<'0'||ch>'9');x=ch^'0';while((ch=gc)>='0'&&ch<='9')x=(x<<1)+(x<<3)+(ch^'0');return x; } const int N=52,K=1005,QWQ=67000; int dp[N][QWQ],fac[N*K],facinv[N*K],mi[N*K],tmp[QWQ]; inline int fast_pow(int x,int k,int ans=1) { for(;k;k>>=1,x=(lint)x*x%p) (k&1)?ans=(lint)ans*x%p:0;return ans; } inline int sol(int x,int s) { return (s&1)?(x?p-x:0):x; } inline int C(int n,int m) { return (lint)fac[n]*facinv[m]%p*facinv[n-m]%p; } namespace NTT_space{const int N=67000;int r[N],*dwg[N],*dwgi[N];inline int prelude_dwg(){int n=N-2;for(int i=2,t=1;i<=n;i<<=1,t++){dwg[t]=new int[i],dwgi[t]=new int[i];int *d=dwg[t],*di=dwgi[t];d[0]=di[0]=1;int w=fast_pow(3,(p-1)/i),wi=fast_pow(3,p-1-(p-1)/i);rep(j,1,i-1) d[j]=(lint)d[j-1]*w%p,di[j]=(lint)di[j-1]*wi%p;}return 0;}inline int pre(int m){int n=1,L=0;while(n<=m) n<<=1,L++;rep(i,1,n-1) r[i]=(r[i>>1]>>1)|((i&1)<<(L-1));return n;}inline int NTT(int *a,int n,int s){rep(i,1,n-1) if(i<r[i]) swap(a[i],a[r[i]]);for(int i=2,c=1;i<=n;i<<=1,c++){int *d=(s>0?dwg[c]:dwgi[c]);for(int j=0,t=i>>1,x,y;j<n;j+=i) rep(k,0,t-1)x=a[j+k],y=(lint)d[k]*a[j+k+t]%p,a[j+k]=x+y,(a[j+k]>=p?a[j+k]-=p:0),a[j+k+t]=x-y,(a[j+k+t]<0?a[j+k+t]+=p:0);}if(s<0) for(int i=0,v=fast_pow(n,p-2);i<n;i++) a[i]=(lint)a[i]*v%p;return 0;} }using NTT_space::NTT; inline int prelude(int n,int k) {dp[0][0]=1;int m=max(n,n*(k-1));rep(i,fac[0]=1,m) fac[i]=(lint)fac[i-1]*i%p;facinv[m]=fast_pow(fac[m],p-2);for(int i=m-1;i>=0;i--) facinv[i]=(i+1ll)*facinv[i+1]%p;int t=NTT_space::pre(n*(k-1));NTT(dp[0],t,1);rep(i,0,k-1) tmp[i]=facinv[i];NTT(tmp,t,1);rep(i,1,n) rep(j,0,t-1) dp[i][j]=(lint)dp[i-1][j]*tmp[j]%p;rep(i,1,n) NTT(dp[i],t,-1);rep(i,1,n) rep(j,0,i*(k-1)) dp[i][j]=(lint)dp[i][j]*fac[j]%p;return 0; } int main() {NTT_space::prelude_dwg();int n=inn(),k=inn(),ans=0;prelude(n,k);rep(i,1,n){int s=0,v=fast_pow(i,p-2);rep(j,mi[0]=1,i*(k-1)+1)mi[j]=(lint)mi[j-1]*v%p;rep(j,0,i*(k-1))s=(s+(lint)mi[j+1]*dp[i][j])%p;ans+=sol((lint)C(n,i)*s%p,i+1);if(ans>=p) ans-=p;}return !printf("%lld\n",(lint)ans*n%p); }

總結

以上是生活随笔為你收集整理的[集训队作业2018]uoj 449 喂鸽子 - min-max容斥 - dp - NTT的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。