zoukankan      html  css  js  c++  java
  • [WC2018]州区划分(状压DP+FWT/FMT)

    很裸的子集反演模板题,套上一些莫名其妙的外衣。

    先预处理每个集合是否合法,再作显然的状压DP。然后发现可以写成子集反演的形式,直接套模板即可。

    子集反演可以看这里

    子集反演的过程就是多设一维代表集合大小,再FMT处理集合并卷积。

    然而我的FMT常数过大,而并卷积又可以用FWT实现,于是就写FWT了。(实际上就三行的区别)

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<cstring>
     4 #define rep(i,l,r) for (int i=(l); i<=(r); i++)
     5 using namespace std;
     6 
     7 const int N=22,mod=998244353;
     8 int n,m,p,x,y,mp[N][N],w[N],fa[N],a[N],d[N],sm[1<<N],sz[1<<N],lg[1<<N],f[N][1<<N],g[N][1<<N];
     9 
    10 int pow(int a,int b){ return b==0 ? 1 : (b==1 ? a : 1ll*a*a%mod); }
    11 int get(int x){ return (fa[x]==x) ? x : fa[x]=get(fa[x]); }
    12 
    13 int ksm(int a,int b){
    14     int res=1;
    15     for (; b; a=1ll*a*a%mod,b>>=1)
    16         if (b & 1) res=1ll*res*a%mod;
    17     return res;
    18 }
    19 
    20 void init(){
    21     rep(i,0,n) lg[1<<i]=i;
    22     rep(S,1,(1<<n)-1){
    23         int t=S&-S,tot=0;
    24         sm[S]=sm[S^t]+w[lg[t]]; sz[S]=sz[S^t]+1;
    25         for (int i=S; i; i=i^(i&-i)) a[++tot]=lg[i&-i];
    26         rep(i,1,tot) fa[a[i]]=a[i],d[a[i]]=0;
    27         rep(i,1,tot){
    28             rep(j,1,tot) if (mp[a[i]][a[j]]) d[a[i]]^=1,fa[get(a[i])]=get(a[j]);
    29             if (d[a[i]]) { g[sz[S]][S]=1; break; }
    30         }
    31         int f=get(a[1]);
    32         rep(i,2,tot) if (f!=get(a[i])){ g[sz[S]][S]=1; break; }
    33     }
    34     rep(i,0,(1<<n)-1) sm[i]=pow(sm[i],p),g[sz[i]][i]=1ll*g[sz[i]][i]*sm[i]%mod;
    35 }
    36 
    37 void FMT(int a[],int n,int f){
    38     for (int i=1; i<n; i<<=1)
    39         rep(j,0,n-1) if (j&i) a[j]=(a[j]+1ll*f*a[j^i]+mod)%mod;
    40 }
    41 
    42 void solve(){
    43     f[0][0]=1; FMT(f[0],1<<n,1);
    44     rep(i,0,n) FMT(g[i],1<<n,1);
    45     rep(i,1,n){
    46         rep(j,0,(1<<n)-1) rep(x,0,i-1)
    47             f[i][j]=(f[i][j]+1ll*f[x][j]*g[i-x][j])%mod;
    48         FMT(f[i],1<<n,-1);
    49         rep(j,0,(1<<n)-1)
    50             if (sz[j]==i) f[i][j]=1ll*f[i][j]*ksm(sm[j],mod-2)%mod; else f[i][j]=0;
    51         FMT(f[i],1<<n,1);
    52     }
    53     FMT(f[n],1<<n,-1); printf("%d
    ",f[n][(1<<n)-1]);
    54 }
    55 
    56 int main(){
    57     scanf("%d%d%d",&n,&m,&p);
    58     rep(i,1,m) scanf("%d%d",&x,&y),mp[x-1][y-1]=mp[y-1][x-1]=1;
    59     rep(i,0,n-1) scanf("%d",&w[i]);
    60     init(); solve();
    61     return 0;
    62 }
    FMT(TLE)

    FWT:

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<cstring>
     4 #define rep(i,l,r) for (int i=(l); i<=(r); i++)
     5 using namespace std;
     6 
     7 const int N=22,mod=998244353;
     8 int n,m,p,x,y,mp[N][N],w[N],fa[N],a[N],d[N],sm[1<<N],sz[1<<N],lg[1<<N],f[N][1<<N],g[N][1<<N];
     9 
    10 int pow(int a,int b){ return b==0 ? 1 : (b==1 ? a : 1ll*a*a%mod); }
    11 int get(int x){ return (fa[x]==x) ? x : fa[x]=get(fa[x]); }
    12 
    13 int ksm(int a,int b){
    14     int res=1;
    15     for (; b; a=1ll*a*a%mod,b>>=1)
    16         if (b & 1) res=1ll*res*a%mod;
    17     return res;
    18 }
    19 
    20 void init(){
    21     rep(i,0,n) lg[1<<i]=i;
    22     rep(S,1,(1<<n)-1){
    23         int t=S&-S,tot=0;
    24         sm[S]=sm[S^t]+w[lg[t]]; sz[S]=sz[S^t]+1;
    25         for (int i=S; i; i=i^(i&-i)) a[++tot]=lg[i&-i];
    26         rep(i,1,tot) fa[a[i]]=a[i],d[a[i]]=0;
    27         rep(i,1,tot){
    28             rep(j,1,tot) if (mp[a[i]][a[j]]) d[a[i]]^=1,fa[get(a[i])]=get(a[j]);
    29             if (d[a[i]]) { g[sz[S]][S]=1; break; }
    30         }
    31         int f=get(a[1]);
    32         rep(i,2,tot) if (f!=get(a[i])){ g[sz[S]][S]=1; break; }
    33     }
    34     rep(i,0,(1<<n)-1) sm[i]=ksm(sm[i],p),g[sz[i]][i]=1ll*g[sz[i]][i]*sm[i]%mod;
    35 }
    36 
    37 void FWT(int a[],int n,int f){
    38     for (int i=2; i<=n; i<<=1)
    39         for (int j=0; j<n; j+=i)
    40             rep(k,j,j+(i>>1)-1)
    41                 a[k+(i>>1)]=(1ll*a[k+(i>>1)]+f*a[k]+mod)%mod;
    42 }
    43 
    44 void solve(){
    45     f[0][0]=1; FWT(f[0],1<<n,1);
    46     rep(i,0,n) FWT(g[i],1<<n,1);
    47     rep(i,1,n){
    48         rep(j,0,(1<<n)-1) rep(x,0,i-1)
    49             f[i][j]=(f[i][j]+1ll*f[x][j]*g[i-x][j])%mod;
    50         FWT(f[i],1<<n,-1);
    51         rep(j,0,(1<<n)-1)
    52             if (sz[j]==i) f[i][j]=1ll*f[i][j]*ksm(sm[j],mod-2)%mod; else f[i][j]=0;
    53         FWT(f[i],1<<n,1);
    54     }
    55     FWT(f[n],1<<n,-1); printf("%d
    ",f[n][(1<<n)-1]);
    56 }
    57 
    58 int main(){
    59     scanf("%d%d%d",&n,&m,&p);
    60     rep(i,1,m) scanf("%d%d",&x,&y),mp[x-1][y-1]=mp[y-1][x-1]=1;
    61     rep(i,0,n-1) scanf("%d",&w[i]);
    62     init(); solve();
    63     return 0;
    64 }
  • 相关阅读:
    linux 批量替换内容
    在Linux下如何查CC攻击?
    mysql init_connect
    利用javascript对字符串加密
    js学习笔记10----字符串的基本操作
    js学习笔记9----时间操作
    3种方法实现列表自动滚动
    如何解决wow.js与fullpage的兼容性
    js兼容获取元素的样式
    用php去除bom头
  • 原文地址:https://www.cnblogs.com/HocRiser/p/10296535.html
Copyright © 2011-2022 走看看