poj2154-color-polyan次二面体+欧拉函数优化
N<=1e9,O(nlogn)的做法会超时。从枚举置换转变为枚举轮换长度,然后可以利用欧拉函数,把复杂度变为O(√n * logn)
1 /*--------------------------------------------------------------------------------------*/ 2 3 #include <algorithm> 4 #include <iostream> 5 #include <cstring> 6 #include <ctype.h> 7 #include <cstdlib> 8 #include <cstdio> 9 #include <vector> 10 #include <string> 11 #include <queue> 12 #include <stack> 13 #include <cmath> 14 #include <set> 15 #include <map> 16 17 //debug function for a N*M array 18 #define debug_map(N,M,G) printf("\n");for(int i=0;i<(N);i++)\ 19 {for(int j=0;j<(M);j++){\ 20 printf("%d",G[i][j]);}printf("\n");} 21 //debug function for int,float,double,etc. 22 #define debug_var(X) cout<<#X"="<<X<<endl; 23 #define LL long long 24 const int INF = 0x3f3f3f3f; 25 const LL LLINF = 0x3f3f3f3f3f3f3f3f; 26 /*--------------------------------------------------------------------------------------*/ 27 using namespace std; 28 29 int N,M,T; 30 int MOD = 1e9+7; 31 32 int Eular(int n) 33 { 34 int ans = n; 35 for(int i=2;i*i<=n;i++) 36 { 37 if(n%i == 0) 38 { 39 ans -= ans/i; 40 while(n%i == 0) n/= i; 41 } 42 } 43 if(n>1) ans -= ans/n; 44 return ans; 45 } 46 int pow_mod(int x,int cnt) 47 { 48 int base = x%MOD,res = 1; 49 while(cnt) 50 { 51 if(cnt&1) {res *= base;res %= MOD;} 52 base *= base;base %= MOD; 53 cnt >>= 1; 54 } 55 return res; 56 } 57 58 int polya(int n,int m) 59 { 60 int res = 0; 61 int i; 62 for(i=1;i*i<n;i++) 63 { 64 if(n%i == 0) 65 { 66 res += Eular(i)%MOD * pow_mod(m,n/i-1)%MOD;res %= MOD; 67 res += Eular(n/i)%MOD * pow_mod(m,i-1)%MOD;res %= MOD; 68 } 69 } 70 if(i*i == n) res += Eular(i)%MOD*pow_mod(m,i-1)%MOD; 71 return res%MOD; 72 } 73 74 int main() 75 { 76 scanf("%d",&T); 77 while(T--) 78 { 79 scanf("%d%d",&N,&MOD); 80 printf("%d\n",polya(N,N)); 81 } 82 }