CF1151F - Sonya and Informatics

1151F - Sonya and Informatics c++

題意:有個長爲n的01序列,求通過K次隨機交換兩個數以後這個序列非降的機率。n <= 100, k <= 1e9。數組

解:看到這個數據範圍想到了矩陣快速冪...ide

先想一個暴力維護每一個位置爲1機率的DP,發現不獨立...spa

而後想到PKUSC T2,單獨肯定每一位,可是這個東西不是排列,有相同的元素很差搞...code

最後想到了thuPC擺傢俱,發現能夠用那個套路。orm

發現最終每一個狀態的機率只跟距初態的距離有關。這裏的距離是兩個狀態異或以後1的個數。blog

因而進行DP,設fij表示前i次操做,所得狀態與初態異或後有j個1的機率。get

轉移有三種,分別是無用轉移,挪一個1到初態的0中,挪一個1到初態的1中。it

而後矩陣快速冪一下。event

最後算答案的時候,咱們還要算出有多少種狀態知足條件,這就是一個組合數。而後除以這個組合數就好了。

  1 #include <bits/stdc++.h>
  2 
  3 const int N = 210, MO = 1e9 + 7;
  4 
  5 int n, K, A[N], fac[N], inv[N], invn[N], a[N][N], ans[N][N], c[N][N], lm;
  6 
  7 inline void Add(int &a, const int &b) {
  8     a += b;
  9     if(a >= MO) a -= MO;
 10     else if(a < 0) a += MO;
 11     return;
 12 }
 13 
 14 inline int qpow(int a, int b) {
 15     int ans = 1;
 16     while(b) {
 17         if(b & 1) {
 18             ans = 1ll * ans * a % MO;
 19         }
 20         a = 1ll * a * a % MO;
 21         b = b >> 1;
 22     }
 23     return ans;
 24 }
 25 
 26 inline int Inv(int x) {
 27     return qpow(x, MO - 2);
 28 }
 29 
 30 inline int iC(int n, int m) {
 31     if(n < 0 || m < 0 || n < m) return 0;
 32     return 1ll * invn[n] * fac[m] % MO * fac[n - m] % MO;
 33 }
 34 
 35 inline void mulself() {
 36     memset(c, 0, sizeof(c));
 37     for(int k = 0; k <= lm; k++) {
 38         for(int i = 0; i <= lm; i++) {
 39             if(!a[i][k]) continue;
 40             for(int j = 0; j <= lm; j++) {
 41                 Add(c[i][j], 1ll * a[i][k] * a[k][j] % MO);
 42             }
 43         }
 44     }
 45     memcpy(a, c, sizeof(a));
 46     return;
 47 }
 48 
 49 inline void mul() {
 50     memset(c, 0, sizeof(c));
 51     for(int k = 0; k <= lm; k++) {
 52         for(int i = 0; i <= lm; i++) {
 53             if(!a[i][k]) continue;
 54             for(int j = 0; j <= lm; j++) {
 55                 Add(c[i][j], 1ll * a[i][k] * ans[k][j] % MO);
 56             }
 57         }
 58     }
 59     memcpy(ans, c, sizeof(c));
 60     return;
 61 }
 62 
 63 int main() {
 64     scanf("%d%d", &n, &K);
 65     int cnt = 0, aim = 0;
 66     for(int i = 1; i <= n; i++) {
 67         scanf("%d", &A[i]);
 68         cnt += A[i];
 69     }
 70     for(int i = 1; i + cnt <= n; i++) {
 71         aim += A[i];
 72     }
 73     //int P = 1ll * Inv(n * (n - 1) / 2) * cnt % MO * (n - cnt) % MO;
 74     int P = Inv(n * (n - 1) / 2);
 75     fac[0] = inv[0] = invn[0] = 1;
 76     fac[1] = inv[1] = invn[1] = 1;
 77     for(int i = 2; i <= n; i++) {
 78         fac[i] = 1ll * i * fac[i - 1] % MO;
 79         inv[i] = 1ll * inv[MO % i] * (MO - MO / i) % MO;
 80         invn[i] = 1ll * invn[i - 1] * inv[i] % MO;
 81     }
 82     
 83     lm = n - cnt;
 84     for(int j = 0; j <= n - cnt; j++) {
 85         int t1 = 1ll * (cnt - j) * (n - cnt - j) % MO * P % MO;
 86         int t2 = 1ll * j * j * P % MO;
 87         Add(a[j][j], (1 - t1 + MO - t2 + MO) % MO);
 88         Add(a[j][j + 1], t1);
 89         Add(a[j][j - 1], t2);
 90     }
 91     for(int i = 0; i <= lm; i++) {
 92         ans[i][i] = 1;
 93     }
 94     
 95     while(K) {
 96         if(K & 1) {
 97             mul();
 98         }
 99         mulself();
100         K >>= 1;
101     }
102     
103     
104     /*f[0][0] = 1;
105     for(int i = 0; i < K; i++) {
106         for(int j = 0; j <= n - cnt; j++) {
107             //Add(f[i + 1][j], (1ll - P + MO) * f[i][j] % MO);
108             int t1 = 1ll * (cnt - j) * (n - cnt - j) % MO * P % MO;
109             int t2 = 1ll * j * j * P % MO;
110             Add(f[i + 1][j + 1], 1ll * f[i][j] * t1 % MO);
111             Add(f[i + 1][j - 1], 1ll * f[i][j] * t2 % MO);
112             Add(f[i + 1][j], 1ll * f[i][j] * ((1 - t1 + MO - t2 + MO) % MO) % MO);
113         }
114     }*/
115     
116     int Ans = 1ll * ans[0][aim] * iC(n - cnt, aim) % MO * iC(cnt, aim) % MO;
117     printf("%d\n", (Ans + MO) % MO);
118     return 0;
119 }
AC代碼

個人理解方式是,有兩個集合S1,S2。S1裏面是初態中爲1的位置,S2是初態中爲0的位置。咱們要往S2裏面放若干個1。每次能夠不改變S2中1的個數,或者從S1拿一個1過來,或者從S2拿一個1出去。

代碼寫的時候沒注意j = 0的邊界,可能會數組越界,可是A了...

相關文章
相關標籤/搜索