AT2143 [ARC062D] AtCoDeerくんとグラフ色塗り / Painting Graphs with AtCoDeer

【题意】

 

【分析】

首先,我们考虑以下情况:

1.一个不在环上的边,贡献为k

2.一个只在一个环上的边,贡献按照polya定理去计算$\frac{\sum \limits_{i=0}^{l-1} k^{\gcd(i, l)}}$

3.一个在多个环相连整体上的边(环贴贴了),那么可以按照插板法来计算贡献 $\binom{l+k-1}{k-1}$

这里至于问什么有贴贴的环就会让所有颜色都能转过来就感性理解一下或者画几个玩玩

【代码】

#include<bits/stdc++.h>
using namespace std;
#define mp make_pair
#define fi first
#define se second
#define lson now<<1
#define rson now<<1|1
typedef long long ll;
const int mod=1e9+7;
const int maxn=205;
int qpow(int a,int b)
{
    int res=1;
    while(b)
    {
        if(b&1) res=1LL*res*a%mod;
        a=1LL*a*a%mod;
        b>>=1;
    }
    return res;
}
int n,m,k,ans=1;
int head[maxn],tot=1;
struct edge
{
    int to,nxt;
}e[maxn<<1];
void add(int x,int y)
{
    e[++tot].to=y; e[tot].nxt=head[x]; head[x]=tot;
}
int inv[maxn],fac[maxn],ifac[maxn],p[maxn];
void init()
{
    p[0]=inv[1]=fac[0]=fac[1]=ifac[1]=ifac[0]=p[0]=1;
    p[1]=k;
    for(int i=2;i<=m+k;i++)
        inv[i]=1LL*inv[mod%i]*(mod-mod/i)%mod,fac[i]=1LL*fac[i-1]*i%mod,
        p[i]=1LL*p[i-1]*k%mod,ifac[i]=1LL*ifac[i-1]*inv[i]%mod;
}
int dfn[maxn],low[maxn],dfstime;
int vis[maxn<<1],s[maxn],top,is[maxn];
int gcd(int x,int y)
{
    if(!y) return x;
    return gcd(y,x%y);
}
void tarjan(int x)
{
    dfn[x]=low[x]=++dfstime;
    for(int i=head[x];i;i=e[i].nxt)
    {
        if(vis[i] || vis[i^1]) continue;
        vis[i]=vis[i^1]=1;  s[++top]=i;
        int to=e[i].to;
        if(!dfn[to])
        {
            tarjan(to);
            low[x]=min(low[to],low[x]);
            if(low[to]>=dfn[x])
            {
                bool cir=1; int res=0,gs=0;
                for(int j=top;s[j+1]!=i;j--,gs++)
                {
                    if(is[e[s[j]].to]) cir=0;
                    else is[e[s[j]].to]=1;
                }
                if(cir)
                {
                    for(int j=0;j<gs;j++)
                        res=(res+p[gcd(gs,j)])%mod;
                    res=1LL*res*inv[gs]%mod;
                }
                else
                {
                    res=1LL*(1LL*fac[gs+k-1]*ifac[k-1]%mod)*ifac[gs]%mod;
                }
                 ans=1LL*ans*res%mod;
                for(;s[top+1]!=i;top--) is[e[s[top]].to]=0;
            }
        }
        else low[x]=min(low[x],dfn[to]);
    }
}
int main()
{
    freopen("a.in","r",stdin);
    freopen("a.out","w",stdout);
    scanf("%d%d%d",&n,&m,&k);
    int x,y;
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d",&x,&y);
        add(x,y); add(y,x);
    }
    init();
    for(int i=1;i<=n;i++)
        if(!dfn[i]) tarjan(i);
    printf("%d",ans);
    return 0;
}

 

posted @ 2021-06-02 21:27  andyc_03  阅读(113)  评论(0编辑  收藏  举报