首先只有一份图时显然可以状压dp,即f[S][i]表示S子集的哈密顿路以i为终点的方案数,枚举下个点转移。

  考虑容斥,我们枚举至少有多少条原图中存在的边(即不合法边)被选进了哈密顿路,统计出这个情况下的哈密顿路数量就可以容斥了。

  考虑暴力,显然是枚举在每张图中选择了哪些不合法边。注意到当固定了某些边被选择后,可以将这些边两端的点缩掉,缩完点之后因为已经进行了容斥,可以假装这是个完全图,哈密顿路径数量显然就是剩余点数的阶乘了,于是只需要考虑选择边的方案数。

  先考虑在一张图中选择边的方案数。之前已经求出了某个子集用一条链串起来的方案数,于是再来一个子集状压dp就搞定了。现在固定了每张图选择边的数量之和,考虑一下生成函数之类的东西容易发现求个多项式快速幂即可。可以直接在点值表示下进行。

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cmath>
  4. #include<cstdlib>
  5. #include<cstring>
  6. #include<algorithm>
  7. using namespace std;
  8. #define ll long long
  9. #define P 998244353
  10. #define N 14
  11. #define M 2100000
  12. char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
  13. int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
  14. int read()
  15. {
  16. int x=0,f=1;char c=getchar();
  17. while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
  18. while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
  19. return x*f;
  20. }
  21. int n,m,k,a[N][N],f[1<<N][N],h[1<<N],g[N][1<<N],u[M],size[1<<N],fac[M],r[M],ans;
  22. void inc(int &x,int y){x+=y;if (x>=P) x-=P;}
  23. int ksm(int a,int k)
  24. {
  25. int s=1;
  26. for (;k;k>>=1,a=1ll*a*a%P) if (k&1) s=1ll*s*a%P;
  27. return s;
  28. }
  29. int inv(int a){return ksm(a,P-2);}
  30. void DFT(int *a,int n,int g)
  31. {
  32. for (int i=0;i<n;i++) r[i]=(r[i>>1]>>1)|(i&1)*(n>>1);
  33. for (int i=0;i<n;i++) if (i<r[i]) swap(a[i],a[r[i]]);
  34. for (int i=2;i<=n;i<<=1)
  35. {
  36. int wn=ksm(g,(P-1)/i);
  37. for (int j=0;j<n;j+=i)
  38. {
  39. int w=1;
  40. for (int k=j;k<j+(i>>1);k++,w=1ll*w*wn%P)
  41. {
  42. int x=a[k],y=1ll*w*a[k+(i>>1)]%P;
  43. a[k]=(x+y)%P,a[k+(i>>1)]=(x-y+P)%P;
  44. }
  45. }
  46. }
  47. }
  48. int main()
  49. {
  50. n=read(),k=read(),m=read();
  51. for (int i=1;i<=m;i++)
  52. {
  53. int x=read(),y=read();
  54. a[x][y]=a[y][x]=1;
  55. }
  56. for (int i=0;i<n;i++) f[1<<i][i]=1;
  57. for (int i=0;i<(1<<n);i++)
  58. {
  59. for (int j=0;j<n;j++)
  60. if (f[i][j])
  61. {
  62. for (int x=0;x<n;x++)
  63. if (!(i&(1<<x))&&a[j][x]) inc(f[i|(1<<x)][x],f[i][j]);
  64. }
  65. for (int j=0;j<n;j++) inc(h[i],f[i][j]);
  66. }
  67. for (int i=1;i<(1<<n);i++) size[i]=size[i^(i&-i)]+1;
  68. g[0][0]=1;
  69. for (int i=0;i<n;i++)
  70. for (int j=1;j<(1<<n);j++)
  71. for (int x=j;x>0;x=x-1&j)
  72. if ((j&-j)==(x&-x)&&i>=size[x]-1) inc(g[i][j],1ll*g[i-(size[x]-1)][j^x]*h[x]%P);
  73. for (int i=0;i<n;i++) u[i]=g[i][(1<<n)-1];
  74. int t=1;while (t<=k*n) t<<=1;
  75. DFT(u,t,3);
  76. for (int i=0;i<t;i++) u[i]=ksm(u[i],k);
  77. DFT(u,t,inv(3));
  78. int v=inv(t);
  79. for (int i=0;i<t;i++) u[i]=1ll*u[i]*v%P;
  80. fac[0]=1;for (int i=1;i<=k*n;i++) fac[i]=1ll*fac[i-1]*i%P;
  81. for (int i=0;i<=k*n;i++)
  82. if (i&1) inc(ans,P-1ll*fac[k*n-i]*u[i]%P);
  83. else inc(ans,1ll*fac[k*n-i]*u[i]%P);
  84. cout<<ans;
  85. return 0;
  86. }
  87.   

#186 path(容斥原理+状压dp+NTT)的更多相关文章

  1. 【bzoj2669】[cqoi2012]局部极小值 容斥原理+状压dp

    题目描述 有一个n行m列的整数矩阵,其中1到nm之间的每个整数恰好出现一次.如果一个格子比所有相邻格子(相邻是指有公共边或公共顶点)都小,我们说这个格子是局部极小值. 给出所有局部极小值的位置,你的任 ...

  2. HDU 4336 容斥原理 || 状压DP

    状压DP :F(S)=Sum*F(S)+p(x1)*F(S^(1<<x1))+p(x2)*F(S^(1<<x2))...+1; F(S)表示取状态为S的牌的期望次数,Sum表示 ...

  3. [LuoguP2167][SDOI2009]Bill的挑战_容斥原理/状压dp

    Bill的挑战 题目链接:https://www.luogu.org/problem/P2167 数据范围:略. 题解: 因为$k$特别小,想到状压. 状压的方式也非常简单,就是暴力枚举. 但是会不会 ...

  4. bzoj 3812: 主旋律 [容斥原理 状压DP]

    3812: 主旋律 题意:一张有向图,求它的生成子图是强连通图的个数.\(n \le 15\) 先说一个比较暴力的做法. 终于知道n个点图的是DAG的生成子图个数怎么求了. 暴力枚举哪些点是一个scc ...

  5. 【uoj#37/bzoj3812】[清华集训2014]主旋律 状压dp+容斥原理

    题目描述 求一张有向图的强连通生成子图的数目对 $10^9+7$ 取模的结果. 题解 状压dp+容斥原理 设 $f[i]$ 表示点集 $i$ 强连通生成子图的数目,容易想到使用总方案数 $2^{sum ...

  6. 【bzoj2560】串珠子 状压dp+容斥原理

    题目描述 有 $n$ 个点,点 $i$ 和点 $j$ 之间可以连 $0\sim c_{i,j}$ 条无向边.求连成一张无向连通图的方案数模 $10^9+7$ .两个方案不同,当且仅当:存在点对 $(i ...

  7. bzoj 2669 题解(状压dp+搜索+容斥原理)

    这题太难了...看了30篇题解才整明白到底咋回事... 核心思想:状压dp+搜索+容斥 首先我们分析一下,对于一个4*7的棋盘,低点的个数至多只有8个(可以数一数) 这样的话,我们可以进行一个状压,把 ...

  8. BZOJ2669 [cqoi2012]局部极小值 状压DP 容斥原理

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ2669 题意概括 有一个n行m列的整数矩阵,其中1到nm之间的每个整数恰好出现一次.如果一个格子比所 ...

  9. 【2016NOIP十连测】【test4】【状压DP】【容斥原理】巨神兵

    题目大意: 给一个n个点(n<=17),m条边的有向图(无自环.无重边),求其无环子图的方案数. 题解: 看到n<=17,显然是用状压dp. 用f[i]表示点集i的满足条件的方案数. 状态 ...

随机推荐

  1. [C#] LINQ之GroupBy

    声明:本文为www.cnc6.cn原创,转载时请注明出处,谢谢! 本文作者文采欠佳,文字表达等方面不是很好,但实际的代码例子是非常实用的,请作参考. 一.先准备要使用的类: 1.Person类: cl ...

  2. React 与 React Native 底层共识:React 是什么

    此系列文章将整合我的 React 视频教程与 React Native 书籍中的精华部分,给大家介绍 React 与 React Native 结合学习的方法,此小节主要介绍 React 的底层原理与 ...

  3. python之面向对象3

     面向对象介绍 一.面向对象和面向过程 面向过程:核心过程二字,过程即解决问题的步骤,就是先干什么后干什么 基于该思想写程序就好比在这是一条流水线,是一种机械式的思维方式 优点:复杂的过程流程化 缺点 ...

  4. 广播频道-BroadcastChannel

    BroadcastChannel,就字面意思来言,叫做“广播频道”,官方文档说,该API是用于同源不同页面之间完成通信的功能. 1. 概况 它与window.postMessage的区别就是,Broa ...

  5. git更新提交代码常用命令

    git pull 拉取代码 git add -A 提交所有变化(包括删除.新增.修改) git commit -m "注释" 本地仓库提交 git push origin mast ...

  6. [2017BUAA软工助教]第0次作业小结

    BUAA软工第0次作业小结 零.题目 作业链接: This is a hyperlink 一.评分规则 本次作业满分10分: 按时提交有分 一周内补交得0分 超过一周不交或抄袭倒扣全部分数 评分规则如 ...

  7. 【转】Linux下cp: omitting directory `XXX'问题解决

    在linux系统中复制文件夹时提示如下: Shell代码 [root@idtp4 site-packages]# /site-packages/ cp: omitting directory ‘yag ...

  8. mybatis源码分析(四)---------------代理对象的生成

    在mybatis两种开发方式这边文章中,我们提到了Mapper动态代理开发这种方式,现在抛出一个问题:通过sqlSession.getMapper(XXXMapper.class)来获取代理对象的过程 ...

  9. AssemblyScript的测试

    详细文档介绍 export function f(x: i32): i32 { if (x === 1 || x === 2) { return 1; } return f(x - 1) + f(x ...

  10. “耐撕”团队 2016.03.31 站立会议

    1. 时间: 19:30--19:50  共计20分钟. 2. 成员: Z 郑蕊 * 组长 (博客:http://www.cnblogs.com/zhengrui0452/), P 濮成林(博客:ht ...