zoukankan      html  css  js  c++  java
  • LOJ#2131. 「NOI2015」寿司晚宴

    $n leq 500$,$2-n$这些数字,两个人挑,可以重复挑,问有几种方案中,一个人选的所有数字与另一个人选的所有数字都互质。

    不像前两题那么抠脚。。

    如果$n$比较小的话,可以把两个人选的数字对应的质因子状压一下,$f(i,j,k)$--前$i$个数,第一个人选状态$j$,第二个人选状态$k$,状态表示质因子。

    质因子的根号相关性质:根号n之后的每个质因子最多只会在一个数里出现一次。也就是说,对根号n前面的质因子我们是可能一次选若干种的,但根号n后面的每个质因子每次只能选一种,所以可以单独枚举,再用根号n以前的状态表示。$g(i,j,k)$--前$i$个含质数$p$的数,只让第一个人选,第二个人保持状态$k$的方案数;$h(i,j,k)$--前$i$个含质数$p$的数,只让第二个人选,第一个人保持状态$j$的方案数。如此dp完,$ans(j,k)$表示最后的$f(i,j,k)$,那么$ans(j,k)=g(t,j,k)+h(t,j,k)-ans(j,k)$,其中$t$表示含质因数$p$的数的个数,因为两个人都不选的方案算了两次。

      1 //#include<iostream>
      2 #include<cstring>
      3 #include<cstdio>
      4 //#include<math.h>
      5 //#include<set>
      6 //#include<queue>
      7 //#include<bitset>
      8 //#include<vector>
      9 #include<algorithm>
     10 #include<stdlib.h>
     11 using namespace std;
     12 
     13 #define LL long long
     14 int qread()
     15 {
     16     char c; int s=0,f=1; while ((c=getchar())<'0' || c>'9') (c=='-') && (f=-1);
     17     do s=s*10+c-'0'; while ((c=getchar())>='0' && c<='9'); return s*f;
     18 }
     19 
     20 //Pay attention to '-' , LL and double of qread!!!!
     21 
     22 int n,mod;
     23 #define maxn 555
     24 int f[2][maxn][maxn],g[2][maxn][maxn],h[2][maxn][maxn],cur=0;
     25 
     26 int prime[maxn],lp,xx[maxn],ss[maxn]; bool notprime[maxn];
     27 void makeprime()
     28 {
     29     ss[2]=0; ss[3]=1; ss[5]=2; ss[7]=3;
     30     ss[11]=4; ss[13]=5; ss[17]=6; ss[19]=7;
     31     for (int i=2;i<=n;i++)
     32     {
     33         if (!notprime[i]) {prime[++lp]=i; xx[i]=i;}
     34         for (int j=1,tmp;j<=lp && 1ll*i*prime[j]<=n;j++)
     35         {
     36             notprime[tmp=i*prime[j]]=1;
     37             xx[tmp]=prime[j];
     38             if (!(i%prime[j])) break;
     39         }
     40     }
     41 }
     42 
     43 int num[maxn],len; int S,P;
     44 void mm(int x)
     45 {
     46     len=0;
     47     while (x>1) {num[++len]=xx[x]; x/=xx[x];}
     48     sort(num+1,num+1+len); len=unique(num+1,num+1+len)-num-1;
     49     S=0; for (int i=1;i<=len;i++) if (num[i]<=19) S|=1<<ss[num[i]];
     50     if (num[len]>19) P=num[len]; else P=0;
     51 }
     52 
     53 int list[maxn][maxn];
     54 void play(int &x,int v) {x+=v; x-=x>=mod?mod:0;}
     55 int main()
     56 {
     57     n=qread(); mod=qread();
     58     makeprime();
     59     for (int i=2;i<=n;i++) {mm(i); list[P][++list[P][0]]=S;}
     60     
     61     int ts=1<<8; f[0][0][0]=1; cur=0;
     62     for (int i=1;i<=list[0][0];i++)
     63     {
     64         int u=list[0][i];
     65         memset(f[cur^1],0,sizeof(f[cur^1]));
     66         for (int j=0;j<ts;j++)
     67             for (int k=0;k<ts;k++) if (f[cur][j][k])
     68             {
     69                 play(f[cur^1][j][k],f[cur][j][k]);
     70                 int nj=j|u; if ((nj&k)==0) play(f[cur^1][nj][k],f[cur][j][k]);
     71                 int nk=k|u; if ((j&nk)==0) play(f[cur^1][j][nk],f[cur][j][k]);
     72             }
     73         cur^=1;
     74     }
     75     
     76     for (int j=0;j<ts;j++)
     77         for (int k=0;k<ts;k++)
     78             f[0][j][k]=f[cur][j][k];
     79     for (int i=2;i<=n;i++) if (!notprime[i])
     80     {
     81         cur=0;
     82         for (int j=0;j<ts;j++)
     83             for (int k=0;k<ts;k++)
     84                 g[0][j][k]=f[0][j][k],h[0][j][k]=f[0][j][k];
     85         for (int t=1;t<=list[i][0];t++)
     86         {
     87             int u=list[i][t];
     88             memset(g[cur^1],0,sizeof(g[cur^1]));
     89             memset(h[cur^1],0,sizeof(h[cur^1]));
     90             for (int j=0;j<ts;j++)
     91                 for (int k=0;k<ts;k++) if (g[cur][j][k])
     92                 {
     93                     play(g[cur^1][j][k],g[cur][j][k]);
     94                     int nj=j|u; if ((nj&k)==0) play(g[cur^1][nj][k],g[cur][j][k]);
     95                 }
     96             for (int j=0;j<ts;j++)
     97                 for (int k=0;k<ts;k++) if (h[cur][j][k])
     98                 {
     99                     play(h[cur^1][j][k],h[cur][j][k]);
    100                     int nk=k|u; if ((j&nk)==0) play(h[cur^1][j][nk],h[cur][j][k]);
    101                 }
    102             cur^=1;
    103         }
    104         for (int j=0;j<ts;j++)
    105             for (int k=0;k<ts;k++)
    106                 f[0][j][k]=((g[cur][j][k]+h[cur][j][k]-f[0][j][k])%mod+mod)%mod;
    107     }
    108     
    109     int ans=0;
    110     for (int j=0;j<ts;j++)
    111         for (int k=0;k<ts;k++)
    112             play(ans,f[0][j][k]);
    113     printf("%d
    ",ans);
    114     return 0;
    115 }
    View Code
  • 相关阅读:
    LeetCode OJ 107. Binary Tree Level Order Traversal II
    LeetCode OJ 116. Populating Next Right Pointers in Each Node
    LeetCode OJ 108. Convert Sorted Array to Binary Search Tree
    LeetCode OJ 105. Construct Binary Tree from Preorder and Inorder Traversal
    LeetCode OJ 98. Validate Binary Search Tree
    老程序员解Bug的通用套路
    转载 四年努力,梦归阿里,和大家聊聊成长感悟
    转载面试感悟----一名3年工作经验的程序员应该具备的技能
    Web Service和Servlet的区别
    关于spring xml文件中的xmlns,xsi:schemaLocation
  • 原文地址:https://www.cnblogs.com/Blue233333/p/9286405.html
Copyright © 2011-2022 走看看