• 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
    ",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 }
  • 相关阅读:
    vs 调试的时候 使用IP地址,局域网的设备可以访问并调试
    jQuery Easing 使用方法及其图解
    win10使用Composer-Setup安装Composer以及使用Composer安装Yii2最新版
    PHP 字符串数组按照拼音排序的问题
    yii2 查询数据库语法
    css禁用鼠标点击事件
    内容显示在HTML页面底端的一些处理方式
    UltraISO制作U盘启动盘
    Swift中使用MPMoviePlayerController实现自定义视频播放器界面
    关于dismissViewControllerAnimated值得注意的一点(deinit)
  • 原文地址:https://www.cnblogs.com/Menhera/p/8988595.html
Copyright © 2020-2023  润新知