hdu 5868:Different Circle Permutation 【Polya计数】

似乎是比较基础的一道用到polya定理的题,为了这道题扣了半天组合数学和数论。

等价的题意:可以当成是给正n边形的顶点染色,旋转同构,两种颜色,假设是红蓝,相邻顶点不能同时为蓝。

大概思路:在不考虑旋转同构的情况下,正n边形有fib(n+1)+fib(n-1)种染色方法(n==1特判),然后后面就是套公式了,涉及到要用欧拉定理优化,不然会T。(理论的东西看下组合数学书中polya计数部分,及数论书中欧拉函数部分中 n的约数的欧拉函数,感觉看博客不如系统的看看书,再结合一下网上一些比较基础的polya题来理解。)

题目链接: http://acm.split.hdu.edu.cn/showproblem.php?pid=5868

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL mod=1e9+7;
LL Eular(LL n)
{
    LL ret=n;
    for(LL i=2; i*i<= n; i++)
    {
        if(n%i==0)
        {
            ret-=ret/i;
            while(n%i==0) n/= i;
        }
    }
    if(n>1) ret-=ret/n;
    return ret;
}
LL qpow(LL n,LL k)
{
    LL res=1;
    for(; k; k>>=1)
    {
        if(k&1) res=res*n%mod;
        n=n*n%mod;
    }
    return res;
}
LL inv(LL x)
{
    return qpow(x,mod-2);
}
const LL N=2;
struct Mat
{
    LL mat[N][N];
};
Mat Mut(Mat a,Mat b)
{
    LL i,j,k;
    Mat c;
    memset(c.mat,0,sizeof(c.mat));
    for(k=0; k<N; k++)
    {
        for(i=0; i<N; i++)
        {
            if(a.mat[i][k])
                for(j=0; j<N; j++)
                {
                    if(b.mat[k][j])
                        c.mat[i][j]=c.mat[i][j]+a.mat[i][k]*b.mat[k][j];
                    c.mat[i][j]=c.mat[i][j]%mod;
                }
        }
    }
    return c;
}
Mat Pow(Mat a,LL n)
{
    Mat c;
    for(int i = 0; i < N; ++i)
        for(int j = 0; j < N; ++j)
            c.mat[i][j] = (i == j);
    for(; n; n>>=1)
    {
        if(n&1)  c=Mut(c,a);
        a=Mut(a,a);
    }
    return c;
}
LL fib(LL x)
{
    if(x==0) return 0;
    Mat A;
    A.mat[0][0]=A.mat[0][1]=A.mat[1][0]=1;
    A.mat[1][1]=0;
    Mat A_=Pow(A,x-1);
    return A_.mat[0][0];
}
LL polya(LL n)
{
    if(n==1) return 2;
    LL ans=0,i;
    for(i=1;i*i<n;i++)
    if(n%i==0)
    {
        ans=(ans+Eular(i)*(fib(n/i-1)+fib(n/i+1)))%mod;
        ans=(ans+Eular(n/i)*(fib(i-1)+fib(i+1)))%mod;
    }
    if(i*i==n) ans+=Eular(i)*(fib(i-1)+fib(i+1))%mod;
    return ans*inv(n)%mod;
}
int main()
{
    LL n;
    while(cin>>n)
        cout<<polya(n)<<'
';
}
原文地址:https://www.cnblogs.com/Just--Do--It/p/6119497.html