题目链接:
SGU 294 He’s Circle
题意:
用两种颜色涂n颗珠子的项链,问本质不同的方案数有多少?考虑旋转。
分析:
很容易根据
Polya
原理得到:
Ans=1n∑d|nn2dϕ(nd)
但是因为 n≤200000 ,并且答案不需要模数。那么难点就在于高精度了。
一开始我把 2 的幂,每步都计算一下,乘以
还要注意最后的除以 n ,一开始是想每次二分找商,后来发现完全没必要, 直接除就好了~~
#include <stdio.h>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <ctime>
using namespace std;
typedef long long ll;
const int MAX_N = 200010;
const int Base = 10000;
const int SIZE = 100010;
int prime_cnt, prime[MAX_N], phi[MAX_N];
int data[SIZE], len, ans[SIZE], ed, n;
void GetPhi()
{
prime_cnt = 0;
phi[1] = 1;
for(int i = 2; i < MAX_N; ++i){
if(phi[i] == 0) {
prime[prime_cnt++] = i;
phi[i] = i - 1;
}
for(int j = 0; j < prime_cnt && i * prime[j] < MAX_N; ++j) {
if(i % prime[j]) {
phi[i * prime[j]] = (prime[j] - 1) * phi[i];
}else {
phi[i * prime[j]] = phi[i] * prime[j];
break;
}
}
}
}
inline void add(int x)
{
int i = 0;
ll carry = 0;
while(carry || i < len) {
carry = carry + ans[i] + data[i] * x;
ans[i] = carry % Base;
carry /= Base;
i++;
}
ed = i;
}
inline void mul(int x)
{
int carry = 0, i = 0;
while(i < len || carry) {
carry = carry + data[i] * x;
data[i] = carry % Base;
carry /= Base;
i++;
}
len = i;
}
inline void div()
{
for(int i = ed, carry = 0; i >= 0; i-- ) {
carry = carry * Base + ans[i];
ans[i] = carry / n;
carry %= n;
}
}
int main()
{
GetPhi();
scanf("%d", &n);
//double begin = clock();
data[0] = 1, len = 1, ed = 0;
int step = 0;
for(int i = 1; i <= n; ++i) {
step++;
if(step == 10) { //这里就是加速!
mul(1 << step);
step = 0;
}
if(n % i) continue;
mul(1 << step);
step = 0;
add(phi[n / i]);
}
div();
for(int i = ed; i >= 0; i--){
if(ans[i] != 0) {
printf("%d", ans[i]);
ed = i - 1;
break;
}
}
for(int i = ed; i >= 0; i--) {
printf("%04d", ans[i]);
}
printf("\n");
//printf("time elapsed : %.6lf Ms\n", clock() - begin);
return 0;
}

该博客探讨了如何运用Polya原理解决SGU 294题目,即计算本质不同的涂色方案数,其中涉及到对项链涂色问题的分析,考虑了旋转的同构性,主要关注高精度计算的应用。
1228

被折叠的 条评论
为什么被折叠?



