状压DP复习

深感自己姿势水平之蒻……一直都不是很会状压DP,NOIP又特别喜欢考,就来复习一发……

题目来源 Orz sqzmz

T1 【BZOJ4197】【NOI2015】寿司晚宴

(做过)质因数分解最大的质因子独自处理,$\sqrt{500}$以内的质数只有八个,因此可以用$2^{16}$的状态来表示一种方案;

然后有同样因子的两个数不能同时出现,排序然后随便搞搞就行了……

 1 #include<algorithm>
 2 #include<iostream>
 3 #include<cstring>
 4 #include<cstdio>
 5 #include<cmath>
 6 using namespace std;
 7 typedef long long ll;
 8 const int p[8]={2,3,5,7,11,13,17,19};
 9 struct num{
10     int n,bigp;
11 }a[501];
12 bool cmp(num a,num b){
13     return a.bigp<b.bigp;
14 }
15 int n,r=256;
16 ll mod,ans,f[256][256],g[2][256][256];
17 int main(){
18     scanf("%d%lld",&n,&mod);
19     for(int i=2;i<=n;i++){
20         int tmp=i;
21         for(int j=0;j<8;j++){
22             if(!(tmp%p[j])){
23                 a[i].n|=(1<<j);
24                 while(!(tmp%p[j]))tmp/=p[j];
25             }
26         }
27         a[i].bigp=tmp;
28     }
29     sort(a+2,a+n+1,cmp);
30     f[0][0]=1;
31     for(int i=2;i<=n;i++){
32         if(i==2||a[i].bigp!=a[i-1].bigp||a[i].bigp==1){
33             memcpy(g[0],f,sizeof(g[0]));
34             memcpy(g[1],f,sizeof(g[1]));
35         }
36         for(int j=r-1;~j;j--){
37             for(int k=r-1;~k;k--){
38                 if((j&k)>0)continue;
39                 if(!(a[i].n&k))g[0][a[i].n|j][k]=(g[0][a[i].n|j][k]+g[0][j][k])%mod;
40                 if(!(a[i].n&j))g[1][j][a[i].n|k]=(g[1][j][a[i].n|k]+g[1][j][k])%mod;
41             }
42         }
43         if(i==n||a[i].bigp!=a[i+1].bigp||a[i].bigp==1){
44             for(int j=r-1;~j;j--){
45                 for(int k=r-1;~k;k--){
46                     if((j&k)>0)continue;
47                     f[j][k]=g[0][j][k]+g[1][j][k]-f[j][k];
48                 }
49             } 
50         }
51     }
52     for(int j=r-1;~j;j--){
53         for(int k=r-1;~k;k--){
54             if((j&k)>0)continue;
55             ans=(ans+f[j][k])%mod;
56         }
57     }
58     ans=(ans+mod)%mod;
59     printf("%lld",ans);
60     return 0;
61 }

T2 【BZOJ1879】【SDOI2009】Bill的挑战

设$f[i][s]$表示到第$i$位,匹配状态为$s$的方案数(S为十五位二进制数),预处理转移状态DP即可。

 1 #include<algorithm>
 2 #include<iostream>
 3 #include<cstring>
 4 #include<cstdio>
 5 #include<cmath>
 6 #include<queue>
 7 #define inf 2147483647
 8 #define eps 1e-9
 9 #define mod 1000003
10 using namespace std;
11 typedef long long ll;
12 int t,n,k,len,ans,bt[65536],p[51][26],f[51][65536];
13 char s[16][51];
14 int main(){
15     for(int i=1;i<65536;i++)bt[i]=bt[i>>1]+(i&1);
16     scanf("%d",&t);
17     while(t--){
18         memset(f,0,sizeof(f));
19         memset(p,0,sizeof(p));
20         ans=0;
21         scanf("%d%d",&n,&k);
22         for(int i=0;i<n;i++){
23             scanf("%s",s[i]);
24         }
25         len=strlen(s[0]);
26         for(int i=0;i<n;i++){
27             for(int j=0;j<len;j++){
28                 if(s[i][j]=='?'){
29                     for(int c=0;c<26;c++)p[j][c]|=(1<<i);
30                 }else p[j][s[i][j]-'a']|=(1<<i);
31             }
32         }
33         f[0][(1<<n)-1]=1;
34         for(int i=0;i<len;i++){
35             for(int j=1;j<(1<<n);j++){
36                 if(f[i][j]){
37                     for(int c=0;c<26;c++){
38                         f[i+1][j&p[i][c]]=(f[i+1][j&p[i][c]]+f[i][j])%mod;    
39                     }
40                 }
41             }
42         }
43         for(int i=0;i<(1<<n);i++){
44             if(bt[i]==k)ans=(ans+f[len][i])%mod;
45         }
46         printf("%d\n",ans);
47     }
48     return 0;
49 }

 

posted @ 2018-10-25 21:27  DCDCBigBig  阅读(133)  评论(0编辑  收藏  举报