[P4921] 情侶?給我燒了!
阿新 • • 發佈:2018-12-26
回顧一下錯排公式
錯排問題:
設n位錯排數為D[n]。考慮元素1的位置,設定為k(有n-1中 );在考慮元素k的位置,
若為1,則轉換為n-2位的錯排;否則,視元素k為元素1(不能放在位置1),轉換為n-1位的錯排。
故 D[n]=(n-1)(D[n-1]+D[n-2]) D[1]=0 D[2]=1
也有公式D[n]=n!/e (e=1-1/1!+1/2!-1/3!+……+(-1)^n*1/n!)
設g(x)為x對情侶都在x排裡都錯開的方案數。
對於詢問的k,其答案=C(n,k)A(n,k)pow(2,k)*g(n-k)
式子從左到右依次表示:
1)在n排中選出k排
2)每對情侶中佔某一排排
3)情侶雙方的位置互調
4)剩下n-k對情侶都要錯開。
然後考慮g(x)的演算法。
這是就要聯想到錯排序列的構造方法。
考慮第一排的情況:
1)倆男(x(x-1)種),考慮他們對應的倆女
a)這倆女在同一排((x-1)2種方案),此時轉化為g(x-2)。
b)這倆女不在同一排, 就把她們當做一對情侶,轉化為g(x-1)
2)倆女,與倆男同
3)左男右女,仔細想想是與倆男還是一樣的。
4)左女右男,仔細想想是與倆男還還是一樣的。
故轉移為g(x)=(1+1+1+1)(x(x-1)((x-1)2*g(x-2)+g(x-1)))=4x(x-1)(2(x-1)g(x-2)+g(x-1))
顯然g(1)=0, g(2)=8 //於是g(0)=1...
時間複雜圖 O(Tn)
#include <bits/stdc++.h> using namespace std; const int N=1e3+7; const int P=998244353; int fac[N]={1}; int inv[N]={0,1}; int fiv[N]={1}; int g[N]={1}; int b[N]={1}; inline int C(int x,int y) { return 1LL*fac[x]*fiv[y]%P*fiv[x-y]%P; } inline int A(int x,int y) { return 1LL*fac[x]*fiv[x-y]%P; } inline int f(int n,int k) { return 1LL*C(n,k)%P*A(n,k)%P*b[k]%P*g[n-k]%P; } int main() { for(int i=1; i<N; ++i) fac[i]=1LL*fac[i-1]*i%P; for(int i=2; i<N; ++i) inv[i]=1LL*(P-P/i)*inv[P%i]%P; for(int i=1; i<N; ++i) fiv[i]=1LL*inv[i]*fiv[i-1]%P; for(int i=2; i<N; ++i) g[i]=4LL*i*(i-1)*(2LL*(i-1)*g[i-2]+g[i-1])%P; for(int i=1; i<N; ++i) b[i]=b[i-1]*2LL%P; int T,n; scanf("%d",&T); while(T--) { scanf("%d",&n); for(int k=0; k<=n; ++k) { printf("%d\n",f(n,k)); } } return 0; }