bzoj 4197 寿司晚宴

4197: [Noi2015]寿司晚宴

Time Limit: 10 Sec  Memory Limit: 512 MB
Submit: 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 }

 

posted on 2017-08-21 14:29  hhhhx  阅读(132)  评论(0编辑  收藏  举报

导航