gym-101873B Buildings(polya計數)
阿新 • • 發佈:2018-12-13
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; }