BZOJ1478: Sgu282 Isomorphism(Polya)

来源:互联网 发布:数据图表 编辑:程序博客网 时间:2024/06/05 01:20

BZOJ传送门
SGU传送门

题意:
给定一个N个结点的无向完全图( 任意两个结点之间有一条边), 现在你可以用 M 种颜色对这个图的每条边进行染色,每条边必须染一种颜色。 若两个已染色的图,其中一个图可以通过结点重新编号而与另一个图完全相同, 就称这两个染色方案相同。 现在问你有多少种本质不同的染色方法,输出结果 modPP 是一个大于N 的质数。

题解:
考虑Polya:
这里写图片描述
这里写图片描述
这里写图片描述

#include<bits/stdc++.h>using namespace std;struct IO{    streambuf *ib,*ob;    inline void init(){        ios::sync_with_stdio(false);        cin.tie(NULL);cout.tie(NULL);        ib=cin.rdbuf();ob=cout.rdbuf();    }    inline int read(){        static char ch;static int i,f;        ch=ib->sbumpc();i=0,f=1;        while(!isdigit(ch)){if(ch=='-')f=-1;ch=ib->sbumpc();}        while(isdigit(ch)){i=(i<<1)+(i<<3)+ch-'0';ch=ib->sbumpc();}        return i*f;    }    inline void W(int x){        static int buf[50];        if(!x){ob->sputc('0');return;}        if(x<0){ob->sputc('-');x=-x;}        while(x){buf[++buf[0]]=x%10;x/=10;}        while(buf[0]){ob->sputc(buf[buf[0]--]+'0');}    }}io;int n,k,mod,ans,cnt,fac[60],inv[60],invfac[60],t[60],gd[60][60];inline int power(int a,int b){    int res=1;    for(;b;b>>=1,a=1ll*a*a%mod)(b&1)?(res=1ll*res*a%mod):0;    return res;}inline int gcd(int x,int y){return y?(gcd(y,x%y)):x;}inline void dfs(int pos,int tot,int last){    if(tot==n){        int tmp=fac[n],last=0,lastcnt=0;        for(int i=1;i<pos;i++)tmp=1ll*tmp*inv[t[i]]%mod;        for(int i=1;i<pos;i++){            if(t[i]!=t[i-1]){                if(lastcnt)tmp=1ll*tmp*invfac[lastcnt]%mod;                last=t[i];lastcnt=1;            }            else lastcnt++;        }        if(lastcnt)tmp=1ll*tmp*invfac[lastcnt]%mod;        (cnt+=tmp)%=mod;        int res=0;        for(int i=1;i<pos;i++){            res+=t[i]/2;            for(int j=1;j<i;j++){                res+=gd[t[i]][t[j]];            }        }        res%=(mod-1);        (ans+=1ll*power(k,res)*tmp%mod)%=mod;        return;    }    int lim=min(last,n-tot);    for(int i=1;i<=lim;i++)t[pos]=i,dfs(pos+1,tot+i,i);}int main(){    io.init();n=io.read(),k=io.read(),mod=io.read();    for(int i=1;i<=n;i++)(i==1)?(fac[i]=1):(fac[i]=1ll*fac[i-1]*i%mod);    for(int i=1;i<=n;i++)(i==1)?(inv[i]=1):(inv[i]=(-1ll*inv[mod%i]*(mod/i)%mod+mod)%mod);    for(int i=1;i<=n;i++)(i==1)?(invfac[i]=1):(invfac[i]=1ll*invfac[i-1]*inv[i]%mod);       for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)gd[i][j]=gcd(i,j);    dfs(1,0,n);    io.W(1ll*ans*power(cnt,mod-2)%mod);}
原创粉丝点击