[WC2018]州区划分

[WC2018]州区划分

注意审题:

1.有序选择

2.若干个州

3.贡献是州满意度的乘积

枚举最后一个州是哪一个,合法时候贡献sum[s]^p,否则贡献0

存在欧拉回路:每个点都是偶度数,且图连通(dfs验证)

然后愉快子集卷积即可。

 

PS:
FMT辣鸡,

FWT可以节省一倍的常数!这样才能通过此题

#include<bits/stdc++.h>
#define reg register int
#define il inline
#define fi first
#define se second
#define mk(a,b) make_pair(a,b)
#define numb (ch^'0')
using namespace std;
typedef long long ll;
template<class T>il void rd(T &x){
    char ch;x=0;bool fl=false;
    while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true);
    for(x=numb;isdigit(ch=getchar());x=x*10+numb);
    (fl==true)&&(x=-x);
}
template<class T>il void output(T x){if(x/10)output(x/10);putchar(x%10+'0');}
template<class T>il void ot(T x){if(x<0) putchar('-'),x=-x;output(x);putchar(' ');}
template<class T>il void prt(T a[],int st,int nd){for(reg i=st;i<=nd;++i) ot(a[i]);putchar('\n');}

namespace Miracle{
const int N=24;
const int mod=998244353;
int n,m,p;
int qm(int x,int y){
    int ret=1;
    while(y){
        if(y&1) ret=(ll)ret*x%mod;
        x=(ll)x*x%mod;
        y>>=1;
    }
    return ret;
}
int ad(int x,int y){
    return x+y>=mod?x+y-mod:x+y;
}
int f[N][1<<21];
int g[N][1<<21];
int w[N],sum[1<<21];
int sz[1<<21];
int to[N];
void FWT(int *f,int n){
    for(reg p=2;p<=n;p<<=1){
        for(reg l=0;l<n;l+=p){
            for(reg k=l;k<l+p/2;++k){
                f[k+p/2]=ad(f[k],f[k+p/2]);
            }
        }
    }
}
void IFWT(int *f,int n){
    for(reg p=2;p<=n;p<<=1){
        for(reg l=0;l<n;l+=p){
            for(reg k=l;k<l+p/2;++k){
                f[k+p/2]=ad(f[k+p/2],mod-f[k]);
            }
        }
    }
}
int val(int v){
    // cout<<" bv "<<v<<endl;
    return p==0?1:(p==1?v:(ll)v*v%mod);
}
int tot;
int vis[N];
int inv[23333];
void dfs(int x,int s){
    // cout<<" x "<<x<<" s "<<s<<endl;
    vis[x]=1;
    ++tot;
    for(reg i=0;i<n;++i){
        if((!vis[i])&&(s&(1<<i))&&(to[x]&(1<<i))){
            dfs(i,s);
        }
    }
}
int main(){
    rd(n);rd(m);rd(p);
    int x,y;
    inv[1]=1;
    for(reg i=2;i<=2500;++i){
        inv[i]=(ll)(mod-mod/i)*inv[mod%i]%mod;
    }
    for(reg i=1;i<=m;++i){
        rd(x);rd(y);--x;--y;
        to[x]|=(1<<y);to[y]|=(1<<x);
    }

    for(reg i=0;i<n;++i){
        rd(w[i]);
    }
    for(reg i=0;i<(1<<n);++i){
        sz[i]=sz[i>>1]+(i&1);
        for(reg j=0;j<n;++j){
            if(i&(1<<j)) sum[i]+=w[j];
        }
    }
    // cout<<" pre 1"<<endl;
    for(reg s=1;s<(1<<n);++s){
        int ji=0;
        tot=0;
        memset(vis,0,sizeof vis);
        
        dfs((__builtin_ctz(s&(-s))),s);
        // cout<<" s "<<s<<" "<<__builtin_ctz(s&(-s))<<" tot "<<tot<<endl;
        // cout<<" tot "<<tot<<" sz "<<sz[s]<<endl;
        if(tot!=sz[s]) ji=233;
        for(reg i=0;i<n;++i){
            if(s&(1<<i)){
                ji+=(sz[to[i]&s]&1);
            }
        }
        // cout<<" ss "<<s<<" ji "<<ji<<endl;
        if(ji>0){
            // cout<<" val "<<val(sum[s])<<endl;
            g[sz[s]][s]=val(sum[s]);
        }
    }
    for(reg i=0;i<(1<<n);++i){
        f[0][i]=1;
    }
    // return 0;
    // cout<<" built "<<endl;
    for(reg i=1;i<=n;++i){
        FWT(g[i],(1<<n));
        // prt(g[i],0,(1<<n)-1);

        for(reg j=1;j<=i;++j){
            for(reg s=0;s<(1<<n);++s){
                f[i][s]=ad(f[i][s],(ll)g[j][s]*f[i-j][s]%mod);
            }
        }
        IFWT(f[i],(1<<n));
        // prt(f[i],0,(1<<n)-1);
        for(reg s=0;s<(1<<n);++s){
            // if(sz[s]==i)
            f[i][s]=(ll)val(inv[sum[s]])*f[i][s]%mod;
            // else f[i][s]=0;
        }
        if(i!=n) FWT(f[i],(1<<n));
    }
    printf("%d",f[n][(1<<n)-1]);
    return 0;
}

}
signed main(){
    Miracle::main();
    return 0;
}

/*
   Author: *Miracle*
   Date: 2019/4/13 19:58:12
*/
View Code

 

posted @ 2019-04-17 21:20  *Miracle*  阅读(755)  评论(0编辑  收藏  举报