解:發現每一個質數只能屬於一我的,因而想到每一個質數有三種狀況:屬於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 }
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 }