洛谷P2150 壽司晚宴

解:發現每一個質數只能屬於一我的,因而想到每一個質數有三種狀況:屬於a,屬於b,都不屬於。c++

而後考慮狀壓每一個人的質數集合,能夠獲得30分。數組

轉移就是外層枚舉每一個數,內層枚舉每一個人的狀態,而後看可否轉移。能轉移就轉移。ide

考慮優化:有個套路是大於√的質數最多隻有一個。因而單獨考慮那些,先把不含那些的轉移出來放到數組f中。優化

而後每次外層枚舉一個質數,中層枚舉它的倍數,內層枚舉兩我的的狀態。spa

每一個質數能夠屬於a或者屬於b或者都不屬於。考慮到轉移屬於a的時候咱們不可避免的會算到都不屬於(除非再開一維記錄),因而容斥一波。3d

屬於a和屬於b由於要分開轉移屢次(中層枚舉倍數),因而用g,h數組分別轉移。code

最後f = g + h - f(容斥掉都不屬於)。blog

其實感受多開一維好想一點......。get

  1 #include <bits/stdc++.h>
  2 
  3 typedef long long LL;
  4 const int N = 510, M = 267;
  5 
  6 int n, sta[N], p[N], top, last[N], id[N], stk[N], tp;
  7 LL f[2][M][M], g[2][M][M], MO, h[2][M][M], F[M][M];
  8 bool vis[N];
  9 
 10 inline void Add(LL &a, const LL &b) {
 11     a += b;
 12     while(a >= MO) a -= MO;
 13     while(a < 0) a += MO;
 14     return;
 15 }
 16 
 17 inline void getp(int n) {
 18     for(int i = 2; i <= n; i++) {
 19         if(!vis[i]) {
 20             p[++top] = i;
 21             id[i] = top;
 22             last[i] = i;
 23         }
 24         for(int j = 1; j <= top && i * p[j] <= n; j++) {
 25             vis[i * p[j]] = 1;
 26             last[i * p[j]] = p[j];
 27             if(i % p[j] == 0) break;
 28         }
 29     }
 30     return;
 31 }
 32 
 33 int main() {
 34 
 35     //freopen("in.in", "r", stdin);
 36 
 37     scanf("%d%lld", &n, &MO);
 38     getp(n);
 39 
 40     int m = 1;
 41     while(m < top && p[m + 1] <= 19) m++;
 42     int lm = 1 << m;
 43 
 44     for(int i = 2; i <= n; i++) {
 45         int x = i, y;
 46         while(x > 1) {
 47             y = last[x];
 48             if(id[y] <= m) sta[i] |= (1 << (id[y] - 1));
 49             else sta[i] |= (1 << m);
 50             while(x % y == 0) x /= y;
 51         }
 52     }
 53 
 54 
 55     LL ans = 0;
 56     f[0][0][0] = 1;
 57     for(int i = 2; i <= n; i++) {
 58         memset(f[(i + 1) & 1], 0, sizeof(f[0]));
 59         if((sta[i] & (lm - 1)) != sta[i]) {
 60             stk[++tp] = i;
 61             memcpy(f[(i + 1) & 1], f[i & 1], sizeof(f[i & 1]));
 62             continue;
 63         }
 64         for(int s = 0; s < lm; s++) {
 65             for(int t = 0; t < lm; t++) {
 66                 if((s & t) || (!f[i & 1][s][t])) continue;
 67                 /// f[i][s][t]
 68                 Add(f[(i + 1) & 1][s][t], f[i & 1][s][t]);
 69                 if((sta[i] & t) == 0) {
 70                     Add(f[(i + 1) & 1][s | sta[i]][t], f[i & 1][s][t]);
 71                 }
 72                 if((sta[i] & s) == 0) {
 73                     Add(f[(i + 1) & 1][s][t | sta[i]], f[i & 1][s][t]);
 74                 }
 75             }
 76         }
 77     }
 78 
 79     for(int s = 0; s < lm; s++) {
 80         for(int t = 0; t < lm; t++) {
 81             if(s & t) continue;
 82             Add(F[s][t], f[(n + 1) & 1][s][t]);
 83         }
 84     }
 85 
 86     for(int i = 1; i <= tp; i++) {
 87         if(vis[stk[i]]) {
 88             continue;
 89         }
 90 
 91         memcpy(g[1], F, sizeof(F));
 92         memcpy(h[1], F, sizeof(F));
 93         int time = 1;
 94         for(int x = stk[i]; x <= n; x += stk[i], time++) {
 95             memset(g[(time + 1) & 1], 0, sizeof(g[0]));
 96             memset(h[(time + 1) & 1], 0, sizeof(h[0]));
 97 
 98             for(int s = 0; s < lm; s++) {
 99                 for(int t = 0; t < lm; t++) {
100                     if(s & t) continue;
101                     Add(g[(time + 1) & 1][s][t], g[time & 1][s][t]);
102                     Add(h[(time + 1) & 1][s][t], h[time & 1][s][t]);
103                     if((sta[time] & t) == 0) {
104                         Add(g[(time + 1) & 1][s | sta[time]][t], g[time & 1][s][t]);
105                     }
106                     if((sta[time] & s) == 0) {
107                         Add(h[(time + 1) & 1][s][t | sta[time]], h[time & 1][s][t]);
108                     }
109                 }
110             }
111         }
112         for(int s = 0; s < lm; s++) {
113             for(int t = 0; t < lm; t++) {
114                 if(s & t) continue;
115                 F[s][t] = -F[s][t];
116                 Add(F[s][t], g[time & 1][s][t]);
117                 Add(F[s][t], h[time & 1][s][t]);
118             }
119         }
120     }
121 
122     for(int s = 0; s < lm; s++) {
123         for(int t = 0; t < lm; t++) {
124             if(s & t) continue;
125             Add(ans, F[s][t]);
126         }
127     }
128 
129     printf("%lld\n", ans);
130     return 0;
131 }
AC代碼(容斥)
  1 #include <bits/stdc++.h>
  2 
  3 typedef long long LL;
  4 const int N = 510, M = 267;
  5 
  6 int n, sta[N], p[N], top, last[N], id[N], stk[N], tp;
  7 LL f[2][M][M], g[2][M][M][2], MO, h[2][M][M][2], F[M][M];
  8 bool vis[N];
  9 
 10 inline void Add(LL &a, const LL &b) {
 11     a += b;
 12     while(a >= MO) a -= MO;
 13     while(a < 0) a += MO;
 14     return;
 15 }
 16 
 17 inline void getp(int n) {
 18     for(int i = 2; i <= n; i++) {
 19         if(!vis[i]) {
 20             p[++top] = i;
 21             id[i] = top;
 22             last[i] = i;
 23         }
 24         for(int j = 1; j <= top && i * p[j] <= n; j++) {
 25             vis[i * p[j]] = 1;
 26             last[i * p[j]] = p[j];
 27             if(i % p[j] == 0) break;
 28         }
 29     }
 30     return;
 31 }
 32 
 33 int main() {
 34 
 35     //freopen("in.in", "r", stdin);
 36 
 37     scanf("%d%lld", &n, &MO);
 38     getp(n);
 39 
 40     int m = 1;
 41     while(m < top && p[m + 1] <= 19) m++;
 42     int lm = 1 << m;
 43 
 44     for(int i = 2; i <= n; i++) {
 45         int x = i, y;
 46         while(x > 1) {
 47             y = last[x];
 48             if(id[y] <= m) sta[i] |= (1 << (id[y] - 1));
 49             else sta[i] |= (1 << m);
 50             while(x % y == 0) x /= y;
 51         }
 52     }
 53 
 54 
 55     LL ans = 0;
 56     f[0][0][0] = 1;
 57     for(int i = 2; i <= n; i++) {
 58         memset(f[(i + 1) & 1], 0, sizeof(f[0]));
 59         if((sta[i] & (lm - 1)) != sta[i]) {
 60             stk[++tp] = i;
 61             memcpy(f[(i + 1) & 1], f[i & 1], sizeof(f[i & 1]));
 62             continue;
 63         }
 64         for(int s = 0; s < lm; s++) {
 65             for(int t = 0; t < lm; t++) {
 66                 if((s & t) || (!f[i & 1][s][t])) continue;
 67                 /// f[i][s][t]
 68                 Add(f[(i + 1) & 1][s][t], f[i & 1][s][t]);
 69                 if((sta[i] & t) == 0) {
 70                     Add(f[(i + 1) & 1][s | sta[i]][t], f[i & 1][s][t]);
 71                 }
 72                 if((sta[i] & s) == 0) {
 73                     Add(f[(i + 1) & 1][s][t | sta[i]], f[i & 1][s][t]);
 74                 }
 75             }
 76         }
 77     }
 78 
 79     for(int s = 0; s < lm; s++) {
 80         for(int t = 0; t < lm; t++) {
 81             if(s & t) continue;
 82             Add(F[s][t], f[(n + 1) & 1][s][t]);
 83         }
 84     }
 85 
 86     for(int i = 1; i <= tp; i++) {
 87         if(vis[stk[i]]) {
 88             continue;
 89         }
 90 
 91         //memcpy(g[1], F, sizeof(F));
 92         //memcpy(h[1], F, sizeof(F));
 93         for(int s = 0; s < lm; s++) {
 94             for(int t = 0; t < lm; t++) {
 95                 g[1][s][t][0] = F[s][t];
 96                 g[1][s][t][1] = 0;
 97                 h[1][s][t][0] = F[s][t];
 98                 h[1][s][t][1] = 0;
 99             }
100         }
101 
102         int time = 1;
103         for(int x = stk[i]; x <= n; x += stk[i], time++) {
104             memset(g[(time + 1) & 1], 0, sizeof(g[0]));
105             memset(h[(time + 1) & 1], 0, sizeof(h[0]));
106 
107             for(int s = 0; s < lm; s++) {
108                 for(int t = 0; t < lm; t++) {
109                     if(s & t) continue;
110                     Add(g[(time + 1) & 1][s][t][0], g[time & 1][s][t][0]);
111                     Add(g[(time + 1) & 1][s][t][1], g[time & 1][s][t][1]);
112                     Add(h[(time + 1) & 1][s][t][0], h[time & 1][s][t][0]);
113                     Add(h[(time + 1) & 1][s][t][1], h[time & 1][s][t][1]);
114                     if((sta[time] & t) == 0) {
115                         Add(g[(time + 1) & 1][s | sta[time]][t][1], g[time & 1][s][t][0]);
116                         Add(g[(time + 1) & 1][s | sta[time]][t][1], g[time & 1][s][t][1]);
117                     }
118                     if((sta[time] & s) == 0) {
119                         Add(h[(time + 1) & 1][s][t | sta[time]][1], h[time & 1][s][t][0]);
120                         Add(h[(time + 1) & 1][s][t | sta[time]][1], h[time & 1][s][t][1]);
121                     }
122                 }
123             }
124         }
125         for(int s = 0; s < lm; s++) {
126             for(int t = 0; t < lm; t++) {
127                 if(s & t) continue;
128                 //F[s][t] = -F[s][t];
129                 //F[s][t] = 0;
130                 Add(F[s][t], g[time & 1][s][t][1]);
131                 Add(F[s][t], h[time & 1][s][t][1]);
132             }
133         }
134     }
135 
136     for(int s = 0; s < lm; s++) {
137         for(int t = 0; t < lm; t++) {
138             if(s & t) continue;
139             Add(ans, F[s][t]);
140         }
141     }
142 
143     printf("%lld\n", ans);
144     return 0;
145 }
AC代碼(多開一維)
相關文章
相關標籤/搜索