zoukankan      html  css  js  c++  java
  • NOI2015 寿司晚宴

    题目大意

    给出$2$到$n$共$n-1,nle 500$个数字,求从中选出两个集合使得从两个集合内各取任意一个数字互质的方案数。

    简要题解

    要满足题中的条件,其实就是要求两个集合中出现的质因子不同。注意到$n,nle 500$以内的数字,要么只存在一个大于$sqrt{n}$的质因子,要么可以由前$8$个质数分解。对于后者,拉出来用$8$位$bit$表示质因子情况压位DP出$f[i][j][k]$表示从前$i$个数字中取出两个集合内质因子状态分别为$j,k$的方案数;再考虑把前者加到DP中去,对于前者中的数,只需要确定把它放在哪个集合即可,而不需要去记录在状态中,因为我们一次性考虑完所有带这个大于$sqrt{n}$的质因子的数:要么不选,要么只能放到同一个集合中去,这样就可以减少状态同时避免了后效性。

    想的时候确实考虑到所有的合数可以由前$8$个素数筛完,但没有进一步想到如何利用这个性质来简化状态。

    然后就是喜闻乐见地打错下标WA了一发。。

      1 #include <bits/stdc++.h>
      2 using namespace std;
      3 namespace my_header {
      4 #define pb push_back
      5 #define mp make_pair
      6 #define pir pair<int, int>
      7 #define vec vector<int>
      8 #define pc putchar
      9 #define clr(t) memset(t, 0, sizeof t)
     10 #define pse(t, v) memset(t, v, sizeof t)
     11 #define bl puts("")
     12 #define wn(x) wr(x), bl
     13 #define ws(x) wr(x), pc(' ')
     14     const int INF = 0x3f3f3f3f;
     15     typedef long long LL;
     16     typedef double DB;
     17     inline char gchar() {
     18         char ret = getchar();
     19         for(; (ret == '
    ' || ret == '
    ' || ret == ' ') && ret != EOF; ret = getchar());
     20         return ret; }
     21     template<class T> inline void fr(T &ret, char c = ' ', int flg = 1) {
     22         for(c = getchar(); (c < '0' || '9' < c) && c != '-'; c = getchar());
     23         if (c == '-') { flg = -1; c = getchar(); }
     24         for(ret = 0; '0' <= c && c <= '9'; c = getchar())
     25             ret = ret * 10 + c - '0';
     26         ret = ret * flg; }
     27     inline int fr() { int t; fr(t); return t; }
     28     template<class T> inline void fr(T&a, T&b) { fr(a), fr(b); }
     29     template<class T> inline void fr(T&a, T&b, T&c) { fr(a), fr(b), fr(c); }
     30     template<class T> inline char wr(T a, int b = 10, bool p = 1) {
     31         return a < 0 ? pc('-'), wr(-a, b, 0) : (a == 0 ? (p ? pc('0') : p) : 
     32             (wr(a/b, b, 0), pc('0' + a % b)));
     33     }
     34     template<class T> inline void wt(T a) { wn(a); }
     35     template<class T> inline void wt(T a, T b) { ws(a), wn(b); }
     36     template<class T> inline void wt(T a, T b, T c) { ws(a), ws(b), wn(c); }
     37     template<class T> inline void wt(T a, T b, T c, T d) { ws(a), ws(b), ws(c), wn(d); }
     38     template<class T> inline T gcd(T a, T b) {
     39         return b == 0 ? a : gcd(b, a % b); }
     40     template<class T> inline T fpw(T b, T i, T _m, T r = 1) {
     41         for(; i; i >>= 1, b = b * b % _m)
     42             if(i & 1) r = r * b % _m;
     43         return r; }
     44 };
     45 using namespace my_header;
     46 
     47 const int MAXN = 500 + 10;
     48 const int PNUM = 8;
     49 const int SNUM = 1 << 8;
     50 const int PRI[] = {2, 3, 5, 7, 11, 13, 17, 19};
     51 int n, mod;
     52 int fac[MAXN], rem[MAXN];
     53 int f[2][2][MAXN][MAXN], d[2][MAXN][MAXN], (*g)[MAXN];
     54 
     55 void add(int &x, int y) {
     56     x += y;
     57     if (x >= mod)
     58         x -= mod;
     59 }
     60 
     61 int main() {
     62 #ifdef lol
     63     freopen("129.in", "r", stdin);
     64     freopen("129.out", "w", stdout);
     65 #endif
     66 
     67     fr(n, mod);
     68     for (int i = 2; i <= n; ++i) {
     69         rem[i] = i;
     70         for (int j = 0; j < PNUM; ++j)
     71             if (rem[i] % PRI[j] == 0) {
     72                 fac[i] |= 1 << j;
     73                 while (rem[i] % PRI[j] == 0)
     74                     rem[i] /= PRI[j];
     75             }
     76     }
     77     int cur = 0, lst = 1;
     78     d[cur][0][0] = 1;
     79     for (int i = 2; i <= n; ++i)
     80         if (rem[i] == 1) {
     81             swap(cur, lst);
     82             memcpy(d[cur], d[lst], sizeof d[cur]);
     83             for (int j = 0; j < SNUM; ++j)
     84                 for (int k = 0; k < SNUM; ++k) {
     85                     if (!(k & fac[i]))
     86                         add(d[cur][j | fac[i]][k], d[lst][j][k]);
     87                     if (!(j & fac[i]))
     88                         add(d[cur][j][k | fac[i]], d[lst][j][k]);
     89                 }
     90         }
     91     g = d[cur];
     92 
     93     //for (int i = 0; i < 4; ++i) {
     94     //    for (int j = 0; j < 4; ++j)
     95     //        ws(g[i][j]);
     96     //    bl;
     97     //}
     98 
     99     for (int i = 2; i <= n; ++i)
    100         if (rem[i] != 1) {
    101             cur = 0, lst = 1;
    102             memcpy(f[0][cur], g, sizeof f[0][cur]);
    103             memcpy(f[1][cur], g, sizeof f[1][cur]);
    104             for (int y = rem[i], x = y; x <= n; x += y) {
    105                 rem[x] = 1;
    106                 swap(cur, lst);
    107                 memset(f[0][cur], 0, sizeof f[0][cur]);
    108                 memset(f[1][cur], 0, sizeof f[1][cur]);
    109                 for (int j = 0; j < SNUM; ++j)
    110                     for (int k = 0; k < SNUM; ++k) {
    111                         add(f[0][cur][j][k], f[0][lst][j][k]);
    112                         add(f[1][cur][j][k], f[1][lst][j][k]);
    113                         if (!(k & fac[x]))
    114                             add(f[0][cur][j | fac[x]][k], f[0][lst][j][k]);
    115                         if (!(j & fac[x]))
    116                             add(f[1][cur][j][k | fac[x]], f[1][lst][j][k]);
    117                     }
    118             }
    119             for (int j = 0; j < SNUM; ++j)
    120                 for (int k = 0; k < SNUM; ++k)
    121                     g[j][k] = ((f[0][cur][j][k] + f[1][cur][j][k] - g[j][k]) % mod + mod) % mod;
    122         }
    123     int ans = 0;
    124     for (int j = 0; j < SNUM; ++j)
    125         for (int k = 0; k < SNUM; ++k)
    126             add(ans, g[j][k]);
    127     wt(ans);
    128 
    129     return 0;
    130 }
  • 相关阅读:
    Ubuntu下安装、激活并配置Pycharm
    高分辨率下firefox字体和界面自动放大的问题
    Java如何根据IP获取当前定位
    WebSocket介绍和一个简单的聊天室
    java注解处理
    TCP/IP协议三次握手与四次握手流程解析
    mybatis如何做分页处理
    xshell学习笔记
    正交表生成工具 PICT 成对组合覆盖 收藏
    Ready api groovy script 参数化
  • 原文地址:https://www.cnblogs.com/ichn/p/6396606.html
Copyright © 2011-2022 走看看