• 洛谷P2150 寿司晚宴


    解:发现每个质数只能属于一个人,于是想到每个质数有三种情况:属于a,属于b,都不属于。

    然后考虑状压每个人的质数集合,可以得到30分。

    转移就是外层枚举每个数,内层枚举每个人的状态,然后看能否转移。能转移就转移。

    考虑优化:有个套路是大于√的质数最多只有一个。于是单独考虑那些,先把不含那些的转移出来放到数组f中。

    然后每次外层枚举一个质数,中层枚举它的倍数,内层枚举两个人的状态。

    每个质数可以属于a或者属于b或者都不属于。考虑到转移属于a的时候我们不可避免的会算到都不属于(除非再开一维记录),于是容斥一波。

    属于a和属于b因为要分开转移多次(中层枚举倍数),于是用g,h数组分别转移。

    最后f = g + h - f(容斥掉都不属于)。

    其实感觉多开一维好想一点......。

      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
    ", 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
    ", ans);
    144     return 0;
    145 }
    AC代码(多开一维)
  • 相关阅读:
    问题2017S03
    问题2017S02
    高等代数问题1
    无穷积分换元法的严格解释
    线性空间的同构理论
    问题2017S01
    朴素贝叶斯分类
    决策树
    温习MATLAB
    感知机
  • 原文地址:https://www.cnblogs.com/huyufeifei/p/10572058.html
Copyright © 2020-2023  润新知