#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll gcd(ll a,ll b)
{
return b==0?a:gcd(b,a%b);
}
ll qpow[100];
ll s1(ll n, ll t)
{
ll ans=0;
for(ll i=0;i<n;i++)
{
ans+=qpow[gcd(i,n)];
}
return ans/n;
}
ll s2(ll n ,ll t)
{
ll ans=0;
if((n&1))
return (s1(n,t)+qpow[(n+1)/2] )/(2);
else
return (s1(n,t)+(qpow[n/2] + qpow[n/2+1])/2 )/2;
}
int main()
{
ll n,t;
while(~scanf("%lld%lld",&n,&t))
{
qpow[0] = 1;
for (int i = 1; i <= n; i++)
qpow[i] = qpow[i-1] * t;
printf("%lld %lld\n",s1(n,t),s2(n,t));
}
return 0;
}
题意:
给定n,t,t种颜色的n个珠子,可以排列出多少种手串和项链,其中项链不能翻转,但是手串可以。
思路:
旋转:(1/n)sigma(t ^ gcd(i,n))
翻转:
奇数:
一颗珠子自己形成一个循环节,其他对称的成长度为2的循环节
(i)(i+1,i-1)(i+2,i-2)。。。。。
n * t ^ (n/2 +1)
偶数:
有两种情况
i) 一根对称轴平分
(i,i+1)(i-1,i+2)(i-2,i+3)。。。。
这根轴旋转180度回到原位,i的选值有(n/2)种
(n/2)*t^(n/2)
ii) 一根对称轴穿过两个珠子平分
(i)(i+1,i-1)(i+2,i-2)。。。。(i+x)
这根轴旋转180度回到原位,i的选值有(n/2)种
(n/2)*t^(n/2+1)
项链:旋转
手链:旋转,对称