zoukankan      html  css  js  c++  java
  • uoj348【WC2018】州区划分

    题目链接
    直接讲吨吨吨给的标准做法吧。记(f(i,j))表示各个州(可以重叠)的城市数量之和为i,这些州的并集为j的方案数,反正若有两个州之间有交集最后的(|j|)会不等于(i)。有
    (f(i,s)=sum_{s1} sum_{s2}[s1|s2==s] f(i-|s2|,s1)*can(s2) (frac{vals(s2)}{vals(s)})^p)
    (f(i,s)*vals(s)^p=sum_j sum_{|s2|=j} sum_{s1} [s1|s2==s] f(i-j,s1)*can(s2) *vals(s2)^p)
    (g(|s|,s))表示(can(s)*vals(s)^p),先在最开始DWT所有的g,枚举i,j,然后卷一下(f_{i-j})(g_j),只要在dp的过程中一直保持f是已经DWT了的,卷积的复杂度就只有(O(2^n)),记得(f_i)算完以后要IDWT一下乘上(vals(s)^{-p})再DWT。复杂度(O(n^22^n))

    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<iostream>
    #include<vector>
    #include<algorithm>
    #include<cmath>
    #define P puts("lala")
    #define cp cerr<<"lala"<<endl
    #define ln putchar('
    ')
    #define pb push_back
    #define fi first
    #define se second 
    #define mkp make_pair
    using namespace std;
    inline int read()
    {
        char ch=getchar();int g=1,re=0;
        while(ch<'0'||ch>'9') {if(ch=='-')g=-1;ch=getchar();}
        while(ch<='9'&&ch>='0') re=(re<<1)+(re<<3)+(ch^48),ch=getchar();
        return re*g;
    }
    typedef long long ll;
    typedef pair<int,int> pii;
    
    const int N=25;
    const int mod=998244353;
    inline ll qpow(ll a,int n)
    {
    	ll ans=1;
    	for(;n;n>>=1,a=a*a%mod) if(n&1) ans=ans*a%mod;
    	return ans;
    }
    
    void FWT(int *a,int n,ll f)
    {
    	for(int step=1;step<n;step<<=1)
    		for(int j=0;j<n;j+=(step<<1))
    			for(int k=j;k<j+step;++k)
    			{
    				int x=a[k],y=a[k+step];
    				a[k+step]=(y+f*x+mod)%mod;
    			}
    }
    
    int head[N],cnt=0;
    struct node
    {
    	int to,next;
    }e[N*N];
    inline void add(int x,int y)
    {
    	e[++cnt]=(node){y,head[x]}; head[x]=cnt;
    	e[++cnt]=(node){x,head[y]}; head[y]=cnt;
    }
    int val[N],n,m,vals[1<<21|1],deg[N],fa[N];
    bool can[1<<21|1];
    pii edg[N*N];
    
    inline int find(int x)
    {
    	if(fa[x]!=x) return fa[x]=find(fa[x]);
    	return fa[x];
    }
    
    int f[23][1<<21|1],g[23][1<<21|1];
    void wj()
    {
    #ifndef ONLINE_JUDGE
    	freopen("walk.in","r",stdin);
    	freopen("walk.out","w",stdout);
    #endif
    }
    int main()
    {
    	wj();
    	n=read(); m=read(); int p=read();
    	for(int i=1;i<=m;++i)
    	{
    		int x=read(),y=read();
    		add(x,y);
    		edg[i]=pii(x,y);
    	}
    	for(int i=1;i<=n;++i) val[i]=read();
    	int tot=1<<n;
    	for(int s=0;s<tot;++s)
    	{
    		int all=0;
    		for(int i=1;i<=n;++i) if(s&(1<<i-1)) vals[s]+=val[i],all++;
    		vals[s]=qpow(vals[s],p);
    		for(int i=1;i<=n;++i) fa[i]=i,deg[i]=0;
    		for(int i=1;i<=m;++i) if((s&(1<<edg[i].fi-1))&&(s&(1<<edg[i].se-1)))
    		{
    			deg[edg[i].fi]++; deg[edg[i].se]++;
    			int r1=find(edg[i].fi),r2=find(edg[i].se);
    			if(r1!=r2) all--;
    			fa[r1]=r2;
    		}
    		can[s]=1;
    		if(all!=1) continue;
    		for(int i=1;i<=n;++i) if(s&(1<<i-1))
    			if(deg[i]&1) {can[s]=1;break;}
    			else can[s]=0;
    	}
    	f[0][0]=1;
    	for(int s=0;s<tot;++s) 
    		g[__builtin_popcount(s)][s]=can[s]*vals[s],vals[s]=qpow(vals[s],mod-2);
    
    	FWT(f[0],tot,1);
    	for(int i=1;i<=n;++i) FWT(g[i],tot,1);
    	for(int i=1;i<=n;++i)
    	{
    		for(int j=1;j<=i;++j)
    		{
    			for(int k=0;k<tot;++k) f[i][k]=(f[i][k]+1ll*f[i-j][k]*g[j][k])%mod;
    		}
    		if(!p) continue;
    		FWT(f[i],tot,-1);
    		for(int k=0;k<tot;++k) f[i][k]=1ll*f[i][k]*vals[k]%mod;
    		FWT(f[i],tot,1);
    	}
    	FWT(f[n],tot,-1);
    	printf("%d
    ",f[n][tot-1]);
    	return 0;
    }
    
  • 相关阅读:
    数据结构--线性表和链表的基础知识
    OC基础--字符串
    iOS开发知识梳理博文集
    OC基础--数据类型与表达式
    数据结构概述
    数据结构--栈和队列基础知识
    NodeJS Get/Post 参数获取
    NodeJS + express 添加HTTPS支持
    NodeJS 获取系统时间 并格式化输出
    Node.Js + Express 搭建服务器
  • 原文地址:https://www.cnblogs.com/thkkk/p/8443788.html
Copyright © 2011-2022 走看看