题目大意:
项链和手镯都是若干珠子穿成的环形首饰,手镯可以旋转和翻转,但项链只能旋转,给n个珠子,t种颜色,求最后能形成的手镯,项链的数量
这里根据等价类计数的polya定理求解
对于一个置换f,若一种方案经过置换后不改变,那么不改变的点的个数记作C(f)
统计所有的C(f) , 相加之后求和除以置换的种数即可
那么这道题里面
对于项链来说,旋转一个角度,也就是2*PI/n , 那么置换群可表示为
1 2 3 4 .... n
2 3 4 5 ... 1
这里就存在一个循环节
所以方案数为 t^1
自己 写着会发现,循环节的个数就是旋转数和总数的gcd值
那么不动点的个数就是 sigma(t^(gcd(i,n))
对于手镯除了上述情况,还有翻转
对于 n 为奇数,翻转对称轴有n条,这样置换形成的循环节有 (n+1)/2
对于 n 为偶数,翻转对称轴有n条,n/2条是不经过点的,这样置换形成的循环节有 (n)/2
n/2条经过两个点的,这样置换形成的循环节有 (n)/2+1
1 #include <cstdio> 2 #include <cstring> 3 4 using namespace std; 5 #define ll unsigned long long 6 int n , t; 7 ll pow[51]; 8 9 int gcd(int a , int b){return b==0?a:gcd(b , a%b);} 10 11 void init() 12 { 13 pow[1] = t; 14 for(int i=2 ; i<=n ; i++) pow[i] = pow[i-1]*t; 15 } 16 int main() 17 { 18 // freopen("in.txt" , "r" , stdin); 19 while(~scanf("%d%d" , &n , &t)){ 20 init(); 21 ll a=0 , b=0; 22 for(int i=1 ; i<=n ; i++){ 23 a += pow[gcd(i , n)]; 24 } 25 if(n&1) b+= pow[(n+1)/2]*n; 26 else{ 27 b+=(n/2)*(pow[n/2]+pow[n/2+1]); 28 } 29 printf("%lld %lld\n" , a/n , (a+b)/2/n); 30 } 31 }
时间: 2024-10-12 21:03:48