bzoj 4197 寿司晚宴
4197: [Noi2015]寿司晚宴
Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 970 Solved: 609
[Submit][Status][Discuss]
Description
为了庆祝 NOI 的成功开幕,主办方为大家准备了一场寿司晚宴。小 G 和小 W 作为参加 NOI 的选手,也被邀请参加了寿司晚宴。
在晚宴上,主办方为大家提供了 n−1 种不同的寿司,编号 1,2,3,…,n−1,其中第 i 种寿司的美味度为 i+1 (即寿司的美味度为从 2 到 n)。
现在小 G 和小 W 希望每人选一些寿司种类来品尝,他们规定一种品尝方案为不和谐的当且仅当:小 G 品尝的寿司种类中存在一种美味度为 x 的寿司,小 W 品尝的寿司中存在一种美味度为 y 的寿司,而 x 与 y 不互质。
现在小 G 和小 W 希望统计一共有多少种和谐的品尝寿司的方案(对给定的正整数 p 取模)。注意一个人可以不吃任何寿司。
Input
输入文件的第 1 行包含 2 个正整数 n,p,中间用单个空格隔开,表示共有 n 种寿司,最终和谐的方案数要对 p 取模。
Output
输出一行包含 1 个整数,表示所求的方案模 p 的结果。
Sample Input
3 10000
Sample Output
9
HINT
2≤n≤500
0<p≤1000000000
PS:难死我啦
思路:状压DP,对于满足条件的,即X选的那些数的质因子集合,和Y选的那些数的质因子集合&为0,所以,可以预处理出每个数字的质因子,
小于等于根号500的质因子数只有8个。。状压处理,对于大质因子,就放X或者Y或者都不放
1 #include<bits/stdc++.h> 2 using namespace std; 3 4 int n,p; 5 int a[] = {2,3,5,7,11,13,17,19}; 6 int dp[2][(1<<8)+10][(1<<8)+10],pd[2][(1<<8)+10][(1<<8)+10]; 7 int f[600],has[(1<<8)+10][(1<<8)+10]; 8 vector<int > fi,se[505]; 9 10 int main(){ 11 scanf("%d%d",&n,&p); 12 for(int i=2;i<=n;i++){ 13 int x=i; 14 int tmp=0; 15 for(int j=0;j<8;j++){ 16 while(x%a[j]==0){ 17 tmp|=(1<<j); 18 x/=a[j]; 19 } 20 } 21 // cout<<i<<" "<<x<<" "<<tmp<<endl; 22 if(x==1){ 23 f[i]=tmp;fi.push_back(i); 24 } 25 else { 26 f[i]=tmp;se[x].push_back(i); 27 } 28 } 29 int now=0; 30 dp[0][0][0]=1; 31 for(int i=0;i<fi.size();i++){ 32 int x=fi[i]; 33 now^=1; 34 memset(dp[now],0,sizeof(dp[now])); 35 for(int j=0;j<(1<<8);j++){ 36 for(int k=0;k<(1<<8);k++){ 37 if((k&f[x])==0) dp[now][j|f[x]][k]+=dp[now^1][j][k],dp[now][j|f[x]][k]%=p; 38 if((j&f[x])==0) dp[now][j][k|f[x]]+=dp[now^1][j][k],dp[now][j][k|f[x]]%=p; 39 dp[now][j][k]+=dp[now^1][j][k]%p; 40 dp[now][j][k]%=p; 41 } 42 } 43 } 44 for(int i=2;i<=n;i++){ 45 if(se[i].size()==0) continue; 46 int tmp=now; 47 for(int j=0;j<(1<<8);j++) 48 for(int k=0;k<(1<<8);k++) has[j][k]=pd[tmp][j][k]=dp[tmp][j][k]; 49 50 for(int j=0;j<se[i].size();j++){ 51 now=now^1; 52 memset(dp[now],0,sizeof(dp[now])); 53 int x=se[i][j]; 54 for(int k=0;k<(1<<8);k++){ 55 for(int l=0;l<(1<<8);l++){ 56 if((l&f[x])==0) dp[now][k|f[x]][l]+=dp[now^1][k][l],dp[now][k|f[x]][l]%=p; 57 dp[now][k][l]+=dp[now^1][k][l];dp[now][k][l]%=p; 58 } 59 } 60 } 61 62 for(int j=0;j<se[i].size();j++){ 63 tmp=tmp^1; 64 memset(pd[tmp],0,sizeof(pd[tmp])); 65 int x=se[i][j]; 66 for(int k=0;k<(1<<8);k++){ 67 for(int l=0;l<(1<<8);l++){ 68 if((k&f[x])==0) pd[tmp][k][l|f[x]]+=pd[tmp^1][k][l],pd[tmp][k][l|f[x]]%=p; 69 pd[tmp][k][l]+=pd[tmp^1][k][l];pd[tmp][k][l]%=p; 70 } 71 } 72 } 73 74 for(int j=0;j<(1<<8);j++) 75 for(int l=0;l<(1<<8);l++)dp[now][j][l] += ((pd[tmp][j][l] - has[j][l])%p+p)%p,dp[now][j][l] %= p; 76 77 } 78 79 int sum=0; 80 for(int i = 0; i < (1<<8); ++i) 81 for(int j = 0; j < (1<<8); ++j) if((i&j) == 0)sum += dp[now][i][j],sum %= p; 82 cout<<sum<<endl; 83 return 0; 84 85 }