1. 程式人生 > >gym-101873B Buildings(polya計數)

gym-101873B Buildings(polya計數)

Sample Input 1 Sample Output 1
1 3 1 1
Sample Input 2 Sample Output 2
2 5 2 209728

題意:一個房子,正m邊形,每一面牆n*n的格子,c個顏色可以選擇,旋轉重合算一個方案,問有幾種塗色方案

思路:一面牆的不同方案數為c^(n*n),那麼問題轉化為,這些不同的方案數,塗色,旋轉重合算一個方案。所以用polya計數法,可以看這個部落格菜鳥系列——polya計數法 ,這裡的項鍊例題是可以翻轉的,而本題翻轉不算同一個方案

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
#include<string>
#include<map>
#include<vector>
using namespace std;
#define maxn 600005
typedef long long ll;
const ll mod=1e9+7;
ll mo(ll a,ll pp){
    if(a>=0&&a<pp)return a;
    a%=pp;
    if(a<0)a+=pp;
    return a;
}
ll powmod(ll a,ll b,ll pp){
    ll ans=1;
    for(;b;b>>=1,a=mo(a*a,pp)){
        if(b&1)ans=mo(ans*a,pp);
    }
    return ans;
}
ll inv1(ll b){
	return powmod(b,mod-2,mod);
}
ll gcd(ll x,ll y){
	return y?gcd(y,x%y):x;
}
int main(){
    ll n,m,c;
    scanf("%lld%lld%lld",&n,&m,&c);
    ll ans=powmod(c,n*n,mod);
    ll sum=0;
    for(int i=1;i<=m;i++){
    	sum=(sum+powmod(ans,gcd(m,i),mod))%mod;
    }
    sum=sum*inv1(m)%mod;
    printf("%lld\n",sum);
    return 0;
}