HDU4623 CRIME 【状压DP】【同类项合并】

题目大意:

求相邻元素互质的排列个数。

题目分析:

感谢上帝赐给我睡眠,我在凌晨一点之前写完了这道题。

由于互质只与质因数有关,所以我们对于质因数种类相同的数合并为一类,特殊的,1,17,19,23是一类,因为没有数与他们不互质。

那么我们做各个位进制不同的状压DP。转移就是在末尾添加哪个数。

代码:

 1 #include<cstdio>
 2 #include<cstdlib>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<vector>
 6 #include<iostream>
 7 using namespace std;
 8 
 9 #define P __gcd
10 
11 int n,mod;
12 int tot,res,maxx;
13 
14 int GCD[30][30];
15 int a[14];
16 //1,2,3,5,2*3,7,2*5,11,13,2*7,3*5,3*7,2*11,2*13
17 int bel[30]={0,0,1,2,1,3,4,5,1,2,6,7,4,8,9,10,1,0,4,0,6,11,12,0,4,3,13,2,9};
18 int data[14]={1,2,3,5,6,7,10,11,13,14,15,21,22,26};
19 int sum[14];
20 int fac[6]={1,1,2,6,24,120};
21 
22 int f[1800000][14];
23 
24 void GetSubSet(){
25     memset(a,0,sizeof(a));maxx=0;
26     for(int i=1;i<=n;i++) a[bel[i]]++,maxx=max(maxx,bel[i]);
27     sum[0] = 1;
28     for(int i=1;i<=maxx;i++) sum[i] = sum[i-1]*a[i-1]+sum[i-1];
29 }
30 
31 vector<int> v[29];
32 void dfs(int now,int dd,int num){
33     if(now > maxx){
34     v[num].push_back(dd);
35     }else{
36     for(int i=0;i<=a[now];i++){
37         dfs(now+1,dd+i*sum[now],num+i);
38     }
39     }
40 }
41 
42 int nw[15];
43 void work(){
44     for(int i=0;i<=maxx;i++) f[sum[i]][i] = 1;
45     for(int i=0;i<=n;i++) v[i].clear();
46     dfs(0,0,0);
47     for(int i=1;i<n;i++){
48     for(int j=0;j<v[i].size();j++){
49         int p=v[i][j];
50         for(int k=maxx;k>=0;k--){nw[k] = p/sum[k];p%=sum[k];}
51         p = v[i][j];
52         for(int k=0;k<=maxx;k++){
53         if(nw[k] == 0 || f[p][k]==0) continue;
54         for(int l=0;l<=maxx;l++){
55             if(a[l]-nw[l] == 0||GCD[l][k]!=1) continue;
56             f[p+sum[l]][l] += f[p][k];
57             f[p+sum[l]][l] %= mod;
58         }
59         }
60     }
61     }
62     int ans = 0;
63     for(int i=0;i<=maxx;i++) ans = (ans+f[v[n][0]][i])%mod;
64     for(int i=0;i<=maxx;i++) 
65         ans=(ans*fac[a[i]])%mod;
66     printf("%d\n",ans);
67 }
68 
69 int main(){
70     int t; scanf("%d",&t);
71     for(int i=0;i<14;i++)for(int j=0;j<14;j++)GCD[i][j]=P(data[i],data[j]);
72     while(t--){
73     scanf("%d%d",&n,&mod);
74     memset(f,0,sizeof(f));
75     GetSubSet();
76     work();
77     }
78     return 0;
79 }

猜你喜欢

转载自www.cnblogs.com/Menhera/p/8988595.html