题目大意:给定一个n个点的环,可以旋转和翻转,要求涂上c种不同的颜色,问等价类数目
首先我们不考虑翻转 假设一次旋转k个位置 那么循环个数显然是Gcd(n,i)
现在考虑翻转 易知所有的置换都可以由【沿着某个固定的对称轴翻转】和【旋转】两步组成
观察一个环 比如我们将对称轴设定为1号节点与圆心的连线 一次旋转k个位置
那么每次置换x会被换到((n+2)-x+k-1)%n+1的位置
我们会发现置换两次之后x就回到了原位
乍一看每个置换都是(AB)(CD)(EF)这样的形式 但是我们忽视了可能一个点置换后还在原点的情况
此时2x≡k+2 (mod n)
由于x<=n,因此等式成立只有两种情况:
2x=k+2 或 2x=n+k+2
当n为奇数时 k+2与n+k+2异号 两个等式中只有一个可以成立 置换是(A)(BC)(DE)(FG)的形式
当n为偶数时
如果k是奇数 那么k+2和n+k+2都是奇数 等式无解 置换是(AB)(CD)(EF)(GH)的形式
如果k是偶数 那么k+2和n+k+2都是偶数 等式有两个解 置换是(A)(B)(CD)(EF)(GH)的形式
因此对于每种置换我们都能求出循环的个数,用所有c的循环个数次幂之和除以置换数2n就是答案
注意n<=2时翻转与否是同一置换,因此每个置换被计算了两次,但是平均值不变,不影响答案
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; int n,c; long long Quick_Power(long long x,long long y) { long long re=1; while(y) { if(y&1) re*=x; x*=x; y>>=1; } return re; } int main() { int i; while(cin>>c>>n,c||n) { long long ans=0; for(i=0;i<n;i++) { ans+=Quick_Power(c,__gcd(n,i)); if(n&1) ans+=Quick_Power(c,n+1>>1); else ans+=Quick_Power(c,(n>>1)+(~i&1)); } cout<<ans/2/n<<endl; } return 0; }
原文地址:http://blog.csdn.net/popoqqq/article/details/42967491