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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

Jzoj5429 排列

發布時間:2024/9/5 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Jzoj5429 排列 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

有兩個長度為n的排列A和B,定義排列的價值f(A,B)為所有滿足A[i]>B[i]的位置i的數量。
現給出n,A,B和S,其中A和B中有一些位置的數未知,問有多少種可能的填數的方案使得f(A,B)=S

保證不存在一個位置i滿足A[i]=0且B[i]=0

十分有趣的題目,是個神奇的組合數學+dp

我們先將問題拆成兩個,因為題目保證沒有A[i]=B[i]=0的位置

我們將所有A[i]=0的B[i]取出來,將這些元素排序得到x

再將所有不在A中的元素取出來排序得到y,設長度為m

那么,我們設一個dp

f[i][j]表示已經做到第i個數,其中已經保證有j個位置有貢獻,其余位置情況不清楚的方案數

那么f[i][j]=f[i-1][j]+f[i-1][j-1]*(k-j){ k是滿足x[k-1]<y[i]的最大的k }

我們令g[j]表示f[m][j]*(m-j)! 這樣就得到了最終的方案數(因為對于其余位置不清楚的情況,可以隨意調換位置)

我們現在可以用容斥原理來計算貢獻恰好為j的g'[j],那么顯然g'[m]=g[m]

讓后可以得到g'[j]=g[j]-Σg'[i]*C(j,i) {j<i<=m} 倒序計算即可

讓后類似的我們可以將B[i]=0的A[i]取出來做一次類似的dp,也求出一個g''

那么答案就是Σg'[i]*g''[i-s](0<=i<=S)

感覺講的比較不清楚,可以好好理解一下

(十月份都是什么題啊!!!!!!!)

#pragma GCC optimize("O3") #pragma G++ optimize("O3") #include<stdio.h> #include<string.h> #include<algorithm> #define N 4010 #define LL long long #define M 1000000007 using namespace std; bool va[N],vb[N]; int a[N],b[N],n,m,s,x[N],y[N]; LL js[N],inv[N],f[N],g[N],Answer=0; inline LL C(int n,int m){ return js[n]*inv[m]%M*inv[n-m]%M; } inline LL pow(LL x,int k,LL S=1){for(;k;x=x*x%M,k>>=1) if(k&1) S=S*x%M;return S; } int main(){freopen("arrange.in","r",stdin);freopen("arrange.out","w",stdout);scanf("%d%d",&n,&s);for(int i=*js=*inv=1;i<=n;++i) js[i]=js[i-1]*i%M;for(inv[n]=pow(js[n],M-2);;) break;for(int i=n;i;--i) inv[i-1]=inv[i]*i%M; for(int i=1;i<=n;++i){scanf("%d",a+i);va[a[i]]=1;}for(int i=1;i<=n;++i){scanf("%d",b+i); vb[b[i]]=1;if(a[i]&&b[i]&&a[i]>b[i]) --s;}m=0;for(int i=1;i<=n;++i) if(!a[i]) x[++m]=b[i];sort(x+1,x+1+m); m=0;for(int i=1;i<=n;++i) if(!va[i]) y[++m]=i;f[0]=1;for(int i=1,k=1;i<=m;++i){for(;k<=m && y[i]>x[k];++k);for(int j=i;j;--j) f[j]=(f[j]+f[j-1]*(k-j))%M;}for(int i=m;~i;--i){f[i]=(f[i]*js[m-i])%M;for(int j=i+1;j<=m;++j) f[i]=(f[i]+M-f[j]*C(j,i)%M)%M;}m=0;for(int i=1;i<=n;++i) if(!b[i]) x[++m]=a[i];sort(x+1,x+1+m); m=0; for(int i=1;i<=n;++i) if(!vb[i]) y[++m]=i;for(int i=1;i<=m;++i) swap(x[i],y[i]);g[0]=1;for(int i=1,k=1;i<=m;++i){for(;k<=m && y[i]>x[k];++k);for(int j=i;j;--j) g[j]=(g[j]+g[j-1]*(k-j))%M;}for(int i=m;~i;--i){g[i]=(g[i]*js[m-i])%M;for(int j=i+1;j<=m;++j) g[i]=(g[i]+M-g[j]*C(j,i)%M)%M;}for(int i=0;i<=s;++i) Answer=(Answer+f[i]*g[s-i]%M)%M;printf("%lld\n",Answer); }

轉載于:https://www.cnblogs.com/Extended-Ash/p/7846031.html

總結

以上是生活随笔為你收集整理的Jzoj5429 排列的全部內容,希望文章能夠幫你解決所遇到的問題。

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