zoukankan      html  css  js  c++  java
  • W17-C-简单环(状压dp)

    先转换成求简单路径(一条链)的数目,然后每条路径一个状态。

    为了避免重复,枚举起点,其他的点的序号都需要比起点大。

    dp[s][j],s表示点集,j表示终点,s点集中最小的序号作为起点。

    状态转移:dp[ s | i ][ i ]  += dp[ s ][ j ]   (if  j->i有边 && s不包含i && i的序号大于起点)

    在递推过程中,会存在许多无用的空状态,跳过就好(不然会超时)

    最后再计算环的数目,注意一个简单环可以表示为两个上述简单路径

    AC代码:

     1 #include<iostream>
     2 #include<stack>
     3 #include<set>
     4 #include<cstring>
     5 #include<cmath>
     6 #include<stdlib.h>
     7 #include<cstdio>
     8 #include<queue>
     9 #include<algorithm>
    10 #include<string>
    11 #include<vector>
    12 #include <queue>
    13 #include <bitset>
    14 #include <limits.h>
    15 using namespace std;
    16 typedef  long long ll;
    17 const ll mo=998244353;
    18 int dp[(1<<20)+100][21];
    19 int e[21][21]={0};
    20 ll kk[50];
    21 ll kpow(ll a,ll b) {
    22     ll ans=1;
    23     while(b){
    24         if(b&1) ans=(ans*a)%mo;
    25         a=(a*a)%mo;
    26         b>>=1LL;
    27     }
    28     return ans;
    29 }
    30 inline int ffs(int x)
    31 {
    32     for(int i=0;i<30;i++)
    33     {
    34         if(x&(1<<i)) return i+1;
    35     }
    36     return 0;
    37 }
    38 inline int popcount(int x)
    39 {   int num=0;
    40     for(int i=0;i<=20;i++)
    41     {
    42         if(x&(1<<i)) num++;
    43     }
    44     return num;
    45 }
    46 int main()
    47 {
    48     ll inv2=kpow(2LL,mo-2);
    49      
    50     int n,m,k;
    51     scanf("%d%d%d",&n,&m,&k);
    52     int x,y;
    53     for(int i=1;i<=m;i++)
    54         {
    55             scanf("%d%d",&x,&y);
    56             e[x][y]=1;
    57             e[y][x]=1;
    58         }
    59      
    60     for(int j=1;j<=n;j++)
    61     {
    62         dp[0|(1<<(j-1))][j]=1;
    63     }
    64     for(int i=1;i<=(1<<n)-1;i++)
    65     {
    66         int x=ffs(i);
    67      for(int j=1;j<=n;j++) if(dp[i][j])
    68     {  
    69          
    70         for( int t=x+1;t<=n;t++)
    71         {   if((i&(1<<(t-1)))||e[j][t]==0) continue;
    72              
    73              
    74             dp[i|(1<<(t-1))][t]=(dp[i|(1<<(t-1))][t]+dp[i][j])%mo;
    75         }
    76         int y=__builtin_popcount(i);
    77         if(e[j][x]&&y>2) kk[y%k]=(kk[y%k]+dp[i][j])%mo;
    78     }      
    79     }
    80  
    81     for(int i=0;i<k;i++)
    82     kk[i]=kk[i]*inv2%mo;
    83      
    84     for(int i=0;i<k;i++)
    85     printf("%lld
    ",kk[i]);
    86     return 0;  
    87 }
  • 相关阅读:
    【前端积累】点击链接切换图片显示
    【Spring Boot && Spring Cloud系列】构建Springboot项目 实现restful风格接口
    【JavaEE企业应用学习记录】验证配置
    optiontransferselect例子
    javascript面向对象(给对象添加属性和方法的方式)
    JavaBean toString方式
    JavaScript 字符串操作
    SQL AND和OR求值顺序
    dom4j解析XML
    SQL使用总结-like,MAX,MIN
  • 原文地址:https://www.cnblogs.com/lnu161403214/p/9186079.html
Copyright © 2011-2022 走看看