zoukankan      html  css  js  c++  java
  • 「WC 2018」州区划分

    题目大意:

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

       

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

    题解:

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

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

      显然我们有转移方程:

        

      $W_S$表示$[G(S,E_S)不存在欧拉回路](sum_{xin 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
    ",f[n][S-1]);
    }
    

      

  • 相关阅读:
    类间关系总结
    Android数据持久化技术
    广播
    活动
    Clean Code
    理解async特性
    async和await构成的异步方法
    ubuntu开启ssh服务
    lumen可以使用laravel-ide-helper
    laravel excel迁移到lumen
  • 原文地址:https://www.cnblogs.com/Troywar/p/9066268.html
Copyright © 2011-2022 走看看