UVA10294 Arif in Dhaka (First Love Part 2)

时间:2021-11-02 11:30:55

题意

PDF

分析

用n颗宝石串成项链和手镯, 每颗宝石的颜色可以t种颜色中的一种,当A类项链经过旋转得B类项链时,A和B属于一类项链, 而手镯不仅可以旋转还可以翻转,当A类手镯经过翻转得得到B类手镯时A和B属于一类手镯,问这n颗宝石,t种颜色,可以串成多少种项链和手镯?

解法:

首先将n颗宝石按顺时针方向编号1,2,3,4,5,6......n

  1. 旋转,当顺时针旋转i颗宝石时, 可以得到一个置换,且这个置换的个数为 (n*i)/gcd(n,i)/i ;由对称性可知 每个循环的阶均相同,故共有gcd(n,i)个不相交循环。此时置换的不动点为 C(f)=t^(gcd(n,i))
  2. 翻转,当n为奇数时,共有(n-1)/2个对称轴,每个对称轴对应一个置换,每个置换包含(n-1)/2个阶为2的循环,一个阶为一的循环,此时C(f)=t^( (n+1)/2 ); 当n为偶数时,不过点的对称轴为n/2个,过点的对称轴有n/2-1, 对于每个不过点的对称轴形成一个置换,包含n/2个阶为2的循环,此时C(f)=t^(n/2); 对于过点的每条对称轴形成一个置换,每个置换包含(n-2)/2个阶为2的循环,两个阶为1的循环,C(f)=t^(n/2+1);
  3. 根据ploy定理,等价类的个数为所有置换不动点的平均值。

时间复杂度\(O(n \log n)\)

代码

#include<iostream>
#include<algorithm>
#define rg register
#define il inline
#define co const
template<class T>il T read(){
rg T data=0,w=1;rg char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') w=-1;ch=getchar();}
while(isdigit(ch)) data=data*10+ch-'0',ch=getchar();
return data*w;
}
template<class T>il T read(rg T&x) {return x=read<T>();}
typedef long long ll; co int maxn=51;
int n,t;
ll pow[maxn],a,b;
int main(){
// freopen(".in","r",stdin),freopen(".out","w",stdout);
while(~scanf("%d%d",&n,&t)){
pow[0]=1;
for(int i=1;i<=n;++i) pow[i]=pow[i-1]*t;
a=0;
for(int i=0;i<n;++i) a+=pow[std::__gcd(i,n)];
b=0;
if(n&1) b=n*pow[(n+1)/2];
else b=n/2*(pow[n/2+1]+pow[n/2]);
printf("%lld %lld\n",a/n,(a+b)/2/n);
}
return 0;
}