1. 程式人生 > >[CFR528(div1)E]Beautiful Matrix(容斥+DP+樹狀數組)

[CFR528(div1)E]Beautiful Matrix(容斥+DP+樹狀數組)

struct font pen main bsp freopen pan pri ace

給一個n*n的矩陣,保證:(1)每行都是一個排列 (2)每行每個位置和上一行對應位置不同。求這個矩陣在所有合法矩陣中字典序排第幾。
考慮類似數位DP的做法,枚舉第幾行開始不卡限制,那麽顯然之前的行都和題給矩陣相同,之後都是錯排。
現在要求的就是,當前行在所有與上一行不交的排列中字典序排第幾。
同樣考慮數位DP,從後往前枚舉到當前位開始不卡限制。用兩個樹狀數組分別維護:(1)這一位之後的數組成的集合 (2)這一位之後當前行和上一行均有的數的集合。
那麽分當前這位是否使用上一行這一位之後存在的數討論,現在要求的就是:在後n-i個位置中,有j個數可能會與上一行重合(也就是(2)中的數),的方案數。
也就是:i位排列有j位要求錯位的方案數dp[i][j]。


我們有:dp[i][j]=dp[i][j-1]-dp[i-1][j-1]。
(或者列出容斥DP式子,發現是一個卷積形式,於是NTT即可)

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #define rep(i,l,r) for (int i=(l); i<=(r); i++)
 5 typedef long long ll;
 6 using namespace std;
 7 
 8 const int N=2010,mod=998244353;
9 int n,ans,b[N],a[N][N],fac[N],dp[N][N],p[N]; 10 11 struct BIT{ 12 int c[N],sum; 13 void clear(){ sum=0; memset(c,0,sizeof c); } 14 void add(int x){ sum++; for (; x<=n; x+=x&-x) c[x]++; } 15 int que(int x){ int res=0; for (; x; x-=x&-x) res+=c[x]; return res; } 16 }t,T;
17 18 void init(){ 19 fac[0]=1; rep(i,1,n) fac[i]=1ll*fac[i-1]*i%mod; 20 dp[1][0]=1; 21 rep(i,2,n){ 22 dp[i][0]=fac[i]; 23 rep(j,1,i) dp[i][j]=(dp[i][j-1]-dp[i-1][j-1]+mod)%mod; 24 } 25 p[0]=1; rep(i,1,n) p[i]=1ll*p[i-1]*dp[n][n]%mod; 26 } 27 28 void add(int x){ if (++b[x]==2) T.add(x); } 29 void inc(int &x,int y){ x+=y; (x>=mod)?x-=mod:0; } 30 31 int main(){ 32 freopen("1085g.in","r",stdin); 33 freopen("1085g.out","w",stdout); 34 scanf("%d",&n); 35 rep(i,1,n) rep(j,1,n) scanf("%d",&a[i][j]); 36 init(); int sm=0; 37 rep(i,1,n) sm=(sm+1ll*fac[n-i]*(a[1][i]-1-t.que(a[1][i]-1)))%mod,t.add(a[1][i]); 38 ans=1ll*sm*p[n-1]%mod; 39 rep(i,2,n){ 40 t.clear(); T.clear(); sm=0; memset(b,0,sizeof(b)); 41 for (int j=n; j; j--){ 42 add(a[i][j]); add(a[i-1][j]); t.add(a[i][j]); 43 int x=T.que(a[i][j]-1),y=t.que(a[i][j]-1)-x,z=T.sum; 44 if (b[a[i-1][j]]==2 && a[i-1][j]<a[i][j]) x--; 45 if (b[a[i-1][j]]==2) z--; 46 sm=(sm+1ll*x*dp[n-j][z-1]%mod+1ll*y*dp[n-j][z]%mod)%mod; 47 } 48 inc(ans,1ll*sm*p[n-i]%mod); 49 } 50 printf("%d\n",ans); 51 return 0; 52 }

[CFR528(div1)E]Beautiful Matrix(容斥+DP+樹狀數組)