zoukankan      html  css  js  c++  java
  • [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('
    ');}
    
    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
  • 相关阅读:
    nginx的rewrite指令
    springmvc上传图片《2》
    cors解决跨域
    java8的Streams
    vue基础篇---路由的实现《2》
    vue基础篇---vue组件《2》
    vue基础篇---watch监听
    ES6新特性
    ubuntu tftp 配置
    驱动程序分层分离概念--总线驱动设备模型
  • 原文地址:https://www.cnblogs.com/Miracevin/p/10726263.html
Copyright © 2011-2022 走看看