题目链接:http://vjudge.net/problem/viewProblem.action?id=11117
就是利用每种等价情形算出置换节之后算组合数
#include <stdio.h> #include <cstring> #include <cstdlib> #include <algorithm> #include <cmath> using namespace std; #define lson o<<1 #define rson o<<1|1 #define max(a,b) (a)>(b)?(a):(b) #define min(a,b) (a)<(b)?(a):(b) #define INF 200000000 typedef long long ll; ll qpow(ll a,int k){ ll ans=1; while(k>0){ if(k&1)ans*=a; a*=a; k>>=1; } return ans; } int gcd(int a,int b){ if(a==0)return b; return gcd(b%a,a); } ll rotation(int n){ ll rot=3; for(int i=2;i<=n;i++){ rot+=qpow(3LL,gcd(i,n)); } return rot; } ll reflection(int n){ ll ref=0; if(n&1){ int cir=n/2+1; ref=qpow(3LL,cir)*n; }else{ ref=(ll)(n/2)*qpow(3LL,n/2); ref+=(ll)(n/2)*qpow(3LL,1+n/2); } return ref; } int main(){ int n; while(~scanf("%d",&n) && n+1){ ll ans; if(!n)ans=0; else ans=(rotation(n)+reflection(n))/(2*n); printf("%I64d\n",ans); } return 0; }