题目大意:

  给一个无向图$G(V,E)$满足$|V|<=21$,对于某一种将$G(V,E)$划分为k个的有序集合方案,若每一个子集$G_i(V_i,E_i)$,$E_i=\{(x,y)|x\in V_i,y\in V_i\}$都不存在欧拉回路,则会对答案贡献为

   

  其中,$x$为集合元素,$w_x$为元素$x$的权值。

题解:

  被题意坑成Cu……我还是太菜了……

  其实很显然我们会得到一个$DP$,设$F_S$为集合$S$划分后的乘积和。

  显然我们有转移方程:

    

  $W_S$表示$[G(S,E_S)不存在欧拉回路](\sum_{x\in S}w_x)^P$

  一个裸的子集卷积的式子。

  时间复杂度$n^2 2^n$

代码:

  

#include "bits/stdc++.h"

using namespace std;

inline int read () {
int s=0,k=1;char ch=getchar();
while (ch<'0'|ch>'9') ch=='-'?k=-1:0,ch=getchar();
while (ch>47&ch<='9') s=s*10+(ch^48),ch=getchar();
return s*k;
} const int mod = 998244353,N=1<<21; inline int powmod (int a,int b) {
int ret=1;
while (b) {
if (b&1) ret=ret*1ll*a%mod;
b>>=1,a=a*1ll*a%mod;
}return ret;
} inline void add (int &x,int y) {
x+=y;
if (x>=mod) x-=mod;
} inline void erase (int &x,int y) {
x-=y;
if (x<0) x+=mod;
} inline void FWT (int *a,int n,int f) {
register int i,j,k;
if (f)
for (i=1;i<n;i<<=1)
for (j=0;j<n;j+=i<<1)
for (k=0;k<i;++k) {
int x=a[j+k],y=a[i+j+k];
erase(y,x);
a[i+j+k] = y;
}
else
for (i=1;i<n;i<<=1)
for (j=0;j<n;j+=i<<1)
for (k=0;k<i;++k) {
int x=a[j+k],y=a[i+j+k];
add(y,x);
a[i+j+k] = y;
}
} int f[22][N],g[22][N],n,m,p,fa[21],w[N],num[N],inv[N],v[N];
int mp[N]; inline int calc (int x) {
if (!p) return 1;
if (p&1) return x;
return x*x;
} int finds (int x) {
return fa[x]==x?x:fa[x]=finds(fa[x]);
} inline int check(int S) {
register int i,j;
static int d[21];
for (i=0;i<n;++i) if (S&(1<<i)) fa[i]=i,d[i]=0;
j=num[S];
for (i=0;i<n;++i)
if (S&(1<<i)) {
for (int x=v[i]&S,t;x;x^=x&-x){
++d[i];
t=mp[x&-x];
++d[t];
if (finds(i)^finds(t))fa[fa[i]]=fa[t],--j;
}
}
if (j>1) return true;
for (i=0;i<n;++i) if (S&(1<<i)) if (d[i]&1)return true;
return false;
} inline void add(int *a,int *b,int *c) {
for (register int i=0;i<(1<<n);++i)
add(a[i],b[i]*1ll*c[i]%mod);
} int main () {
n=read(),m=read(),p=read(); register int i,j,k; for (i=0;i<m;++i) {
int x=read()-1,y=read()-1;
v[x]|=1<<y;
}
int S=1<<n;
for (i=0;i<n;++i)
w[1<<i]=read(),mp[1<<i]=i;
for (i=2;i<S;i<<=1)
for (j=1,k=w[i];j<i;++j) {
int x=w[j];
x=x+k;
w[i|j] = x;
}
for (i=1;i<S;++i) {
num[i] = num[i>>1]+(i&1);
int tmp=w[i];
tmp=calc(tmp);
g[num[i]][i] = check(i) * tmp;
inv[i] = powmod(tmp,mod-2);
}
for (i=0;i<S;++i)
f[0][i]=1; for (i=1;i<=n;++i)
FWT(g[i],S,0),
memcpy(f[i],g[i],sizeof f[i]);
for (i=1;i<=n;++i) {
for (j=1;j<i;++j)
for (k=0;k<S;++k) {
int x=f[i][k],y=g[j][k],z=f[i-j][k];
add(x,1ll*y*z%mod);
f[i][k]=x;
}
FWT(f[i],S,1);
for (j=0;j<S;++j) {
int x=f[i][j],y=inv[j];
x=x*1ll*y%mod;
f[i][j] = x;
}
if (i^n) FWT(f[i],S,0);
}
printf("%d\n",f[n][S-1]);
}

  

最新文章

  1. Swift与C#的基础语法比较
  2. 从H264码流中获取视频宽高 (SPS帧)
  3. 来自于2016.2.24的flag
  4. ios推送:本地通知UILocalNotification
  5. vim编辑器配置修改
  6. POI 简单合并单元格
  7. js调用高德API获取所在当前城市
  8. 【安卓面试题】简述一下Android系统的架构?
  9. 【暑假】[实用数据结构]UVAlive 3026 Period
  10. The Little Redis Book
  11. NOIP2000 乘积最大
  12. 【Shell Basic】Shell脚本编写规范
  13. JAVA课程设计--------五子棋
  14. 面试题&#183;HashMap和Hashtable的区别(转载再整理)
  15. Python基础知识点
  16. PYMySQL的注册功能的实现
  17. c# HTML中提取图片地址
  18. ES 记录之如何创建一个索引映射,以及一些设置
  19. 三篇文章了解 TiDB 技术内幕 —— 谈调度
  20. 移植最新Uboot到JZ2440开发板

热门文章

  1. mysql基础优化-explain的使用-mysql死锁
  2. 大数据批量导入,解决办法,实践从定时从 sqlserver 批量同步数据到 mySql
  3. Roman to Integer(将罗马数字转成整数)
  4. PLSQL Developer使用技巧
  5. [C#]使用 C# 编写自己的区块链挖矿算法
  6. 基于Django的独立运行脚本开发
  7. vfd折腾(二)
  8. Interesting卡常数
  9. python都能做什么
  10. 总结Array类型中常用的方法