求助

P4221 [WC2018] 州区划分

rEdWhitE_uMbrElla @ 2019-02-21 21:15:59

今天是@SLF_LLL_SPFA OI的最后一天,今年年初,两开花,多多关注。。。

但明天我是真的要退役了。。于是这题便成了最后一题

不知道为什么LojAC,LG非要卡常数才能过。。不然15。。即使数据被加强了。。也不至于这样。。想知道哪里写丑了。。

#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
constexpr int N=1<<21,MOD=998244353;

namespace IO{
    inline char gc() {
        static char buf[100000],*p1=buf,*p2=buf;
        return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
    }

    template<typename __Type_of__scan>
    inline void read(__Type_of__scan &x) {
        __Type_of__scan f=1;
        x=0;
        char s=gc();
        while(s<'0'||s>'9') {
            if(s=='-')f=-1;
            s=gc();
        }
        while(s>='0'&&s<='9') {
            x=x*10+s-'0';
            s=gc();
        }
        x*=f;
    }

    char buf[100000],*pp=buf;

    inline void pc(const char c) {
        if(pp-buf==100000)fwrite(buf,1,100000,stdout),pp=buf;
        *pp++=c;
    }

    template<typename __Type_of__preprint>
    inline void fsh(__Type_of__preprint x) {
        if(x<0) {
            pc('-');
            x=-x;
        }
        if(x>9)fsh(x/10);
        pc(x%10+'0');
    }

    template<typename __Type_of__print>
    inline void print(__Type_of__print x) {
        fsh(x);
        fwrite(buf,1,pp-buf,stdout);
        pp=buf;
    }
}

int n,m,ss,p,s[22][22],val[22],deg[22],f[22][N],g[22][N],sum[N],cnt[N],inv[N],rec[N];

namespace math{
    inline int add(const int &x,const int &y) {
        return x+y>=MOD?x+y-MOD:x+y;
    }

    inline int qpow(int x,int y){
        int ans=1;
        while(y) {
            if(y&1) ans=1LL*ans*x%MOD;
            x=1LL*x*x%MOD,y>>=1;
        }
        return ans;
    }

    inline void FWT(int *arr,int n,int op){
        for(int i=1;i<n;i<<=1)
            for(int q=i<<1,j=0;j<n;j+=q)
                for(int k=0;k^i;++k)
                    arr[i+j+k]=math::add(arr[i+j+k],op==1?arr[j+k]:MOD-arr[j+k]);
    }
}

namespace us{
    int fa[N];

    inline void init(int x){
        for(int i=1;i<=x;++i) fa[i]=i;
    }

    inline int find(int x) {
        if(fa[x]!=x) fa[x]=us::find(fa[x]);
        return fa[x];
    }

    inline void merge(int x,int y){
        int fx=us::find(x),fy=us::find(y);
        if(fx!=fy) fa[fx]=fy;
    }
}

int main(){
    IO::read(n),IO::read(m),IO::read(p),ss=1<<n,g[0][0]=inv[0]=inv[1]=1,math::FWT(g[0],ss,1);
    for(int i=2;i<=100*n;++i) inv[i]=1LL*inv[MOD%i]*(MOD-MOD/i)%MOD;
    for(int i=1,x,y;i<=m;++i) IO::read(x),IO::read(y),s[x][y]=s[y][x]=1;
    for(int i=1;i<=n;++i) IO::read(val[i]);
    for(int i=1;i^ss;++i) cnt[i]=cnt[i>>1]+(i&1);
    for(int i=1,lst=0;i^ss;++i){
        us::init(n);
        for(int j=1;j<=n;++j)
            if((1<<(j-1))&i){
                sum[i]=math::add(sum[i],val[j]);
                for(int k=j+1;k<=n;++k)
                    if(s[j][k]&&((1<<(k-1))&i)) ++deg[j],++deg[k],us::merge(j,k);
            }
        for(int j=1;j<=n;++j)
            if(deg[j]&1) {rec[i]=1;break;}
        for(int j=1;j<=n;++j)
            if((1<<(j-1))&i){
                if(lst&&us::find(j)^lst) {rec[i]=1;break;}
                lst=us::find(j);
            }
        lst=0,memset(deg,0,sizeof(deg));
    }
    for(int k=0;k^ss;++k) if(rec[k]) f[cnt[k]][k]=math::qpow(sum[k],p);
    for(int i=1;i<=n;++i){
        math::FWT(f[i],ss,1);
        for(int j=1;j<=i;++j)
            for(int k=0;k^ss;++k)
                g[i][k]=(1LL*f[j][k]*g[i-j][k]+g[i][k])%MOD;
        math::FWT(g[i],ss,-1);
        for(int k=0;k^ss;++k)
            if(cnt[k]^i) g[i][k]=0;
            else g[i][k]=1LL*g[i][k]*math::qpow(inv[sum[k]],p)%MOD;
        if(i^n) math::FWT(g[i],ss,1);
    }
    IO::print(g[n][ss-1]);
}

by RiverFun @ 2019-02-21 21:20:39

所以dalao为什么要退役


by 吴勉之 @ 2019-02-21 21:40:59

蒟蒻只是来前排抢沙发的,路过QAQ

。。。。。。orz(逃)


|