uoj#94集训队互测2015胡策的统计(集合幂级数)

Posted QuartZ_Z

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了uoj#94集训队互测2015胡策的统计(集合幂级数)相关的知识,希望对你有一定的参考价值。

  题目传送门:http://uoj.ac/problem/94

  这是一道集合幂级数的入门题目。我们先考虑求出每个点集的连通生成子图个数,记为$g_S$,再记$h_S$为点集$S$的生成子图个数,容易发现,$h_S=2^{size_S}$,其中$size_S$为点集$S$的极大生成子图内的边数。特殊的,$f_{o}=g_{o}=0$。

  定义集合幂级数的乘法为子集卷积,考虑集合幂级数$h$和$g$的关系,我们可以得到

    $$h=1+sum_{k geq 1}frac{g^k}{k!}=1+e^h$$

 

  因此可得

    $$g=ln{(1+h)}$$

  我们再记$f_S$为点集$S$的生成子图的价值和,可得到

    $$f=1+sum{k geq 1}frac{g^k}{k!}k!=frac{1}{1-g}$$

  计算集合幂级数的对数和逆时,因为我们将乘法定义为子集卷积,所以可以将其映射成集合占位幂级数$f_{|S|,S}$后,在将每个集合对应的位看作形式幂级数再暴力求解。

  代码:

技术图片
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#define mod 998244353
#define Mod1(x) (x>=mod?x-mod:x)
#define Mod2(x) (x<0?x+mod:x)
#define ll long long
inline ll read()
{
    ll x=0; char c=getchar(),f=1;
    for(;c<0||9<c;c=getchar())if(c==-)f=-1;
    for(;0<=c&&c<=9;c=getchar())x=x*10+c-0;
    return x*f;
}
inline void write(ll x)
{
    static int buf[20],len; len=0;
    if(x<0)x=-x,putchar(-);
    for(;x;x/=10)buf[len++]=x%10;
    if(!len)putchar(0);
    else while(len)putchar(buf[--len]+0);
}
inline void writeln(ll x){write(x); putchar(
);}
inline void writesp(ll x){write(x); putchar( );}
int f[25][(1<<20)+5],g[25][(1<<20)+5];
int cnt[(1<<20)+5],inv[25];
int x[410],y[410];
int n,m;
inline ll power(ll a,ll b)
{
    ll ans=1;
    for(;b;b>>=1,a=a*a%mod)
        if(b&1)ans=ans*a%mod;
    return ans;
}
inline void fwt(int* a,int n)
{
    for(int i=1;i<n;i<<=1)
        for(int j=0;j<n;j+=(i<<1))
            for(int k=j;k<j+i;k++)
                a[k+i]=Mod1(a[k+i]+a[k]);
}
inline void ifwt(int* a,int n)
{
    for(int i=1;i<n;i<<=1)
        for(int j=0;j<n;j+=(i<<1))
            for(int k=j;k<j+i;k++)
                a[k+i]=Mod2(a[k+i]-a[k]);
}
int main()
{
    n=read(); m=read();
    for(int i=0;i<m;i++)
        x[i]=read()-1,y[i]=read()-1;
    for(int i=1;i<1<<n;i++)
        cnt[i]=cnt[i>>1]+(i&1);
    for(int i=1;i<1<<n;i++){
        int tot=0;
        for(int j=0;j<m;j++)
            if((i&(1<<x[j]))&&(i&(1<<y[j])))++tot;
        f[cnt[i]][i]=power(2,tot);
    }
    for(int i=1;i<=n;i++)
        fwt(f[i],1<<n);
    for(int i=1;i<=n;i++)
        inv[i]=power(i,mod-2);
    for(int i=1;i<=n;i++){\求ln
        for(int k=0;k<i;k++)
            for(int j=0;j<1<<n;j++)
                g[i][j]=(g[i][j]+(ll)k*g[k][j]%mod*f[i-k][j])%mod;
        for(int j=0;j<1<<n;j++)
            g[i][j]=(f[i][j]+(ll)(mod-inv[i])*g[i][j])%mod;
    }
    memset(f,0,sizeof(f));
    for(int i=0;i<1<<n;i++)
        f[0][i]=1;
    for(int i=1;i<=n;i++)\求逆
        for(int k=0;k<i;k++)
            for(int j=0;j<1<<n;j++)
                f[i][j]=(f[i][j]+(ll)f[k][j]*g[i-k][j])%mod;
    ifwt(f[n],1<<n);
    writeln(f[n][(1<<n)-1]);
    return 0;
}
uoj94

 

以上是关于uoj#94集训队互测2015胡策的统计(集合幂级数)的主要内容,如果未能解决你的问题,请参考以下文章

UOJ #88. 集训队互测2015Robot 李超线段树

UOJ#191. 集训队互测2016Unknown

集训队互测2016Unknown(UOJ191)

P4463 [集训队互测2012] calc 拉格朗日插值 dp 多项式分析

清华集训2015 V

UOJ #164 清华集训2015V (线段树)