【POJ】2154 Color

题意:n个珠子的环,之多着n种颜色,考虑旋转,不考虑翻转。问模P的方案数。

运用Burnside定理,有n个置换,每个置换使得着色不变的着色个数有GCD(n,i)个。

GCD(n,i)个的原因:【POJ】2409 Let it Bead

由于n达到十亿,显然不能枚举。但是可以发现,GCD(n,i)即n约数的个数很少。

问题转化为1~n有多少个数,使得GCD(n,i)=k。其中k是n的约数。这个问题等价于与n/k互质的个数有多少,那么容斥就能搞定。

由于有模P,Burnside定理最后要除以n,但是n与P不一定互质,可能没有逆元。观察到分子,不妨先都除以n,就避免了这个问题。

  1 #include<cstdio>

  2 #include<cstring>

  3 #include<cmath>

  4 #include<vector>

  5 #define EPS 1e-8

  6 #define MAXN 32000

  7 using namespace std;

  8 vector<int> fac;

  9 vector<int> g;

 10 vector<int> prime;

 11 int P;

 12 bool p[MAXN];

 13 void Init() {

 14     int i, j;

 15     memset(p, true, sizeof(p));

 16     for (i = 2; i < 180; i++) {

 17         if (p[i]) {

 18             for (j = i * i; j < MAXN; j += i)

 19                 p[j] = false;

 20         }

 21     }

 22     prime.clear();

 23     for (i = 2; i < MAXN; i++) {

 24         if (p[i])

 25             prime.push_back(i);

 26     }

 27 }

 28 void Factor(int n) {

 29     int i, tmp;

 30     fac.clear();

 31     tmp = (int) (sqrt((double) n) + EPS);

 32     for (i = 1; i <= tmp; i++) {

 33         if (n % i == 0) {

 34             fac.push_back(i);

 35             if (i == tmp && i * i == n)

 36                 continue;

 37             fac.push_back(n / i);

 38         }

 39     }

 40 }

 41 int PowMod(int a, int b, int c) {

 42     int res;

 43     a %= c;

 44     for (res = 1; b; b >>= 1) {

 45         if (b & 1) {

 46             res *= a;

 47             res %= c;

 48         }

 49         a *= a;

 50         a %= c;

 51     }

 52     return res;

 53 }

 54 void Prime(int x) {

 55     int i, tmp;

 56     g.clear();

 57     tmp = (int) (sqrt((double) x) + EPS);

 58     for (i = 0; prime[i] <= tmp; i++) {

 59         if (x % prime[i] == 0) {

 60             g.push_back(prime[i]);

 61             while (x % prime[i] == 0)

 62                 x /= prime[i];

 63         }

 64     }

 65     if (x > 1)

 66         g.push_back(x);

 67 }

 68 int Mul(int x, int &k) {

 69     int i, ans = 1;

 70     for (i = k = 0; x; x >>= 1, i++) {

 71         if (x & 1) {

 72             ans *= g[i];

 73             k++;

 74         }

 75     }

 76     return ans;

 77 }

 78 int Count(int x) {

 79     int i, j, t, tmp, ans;

 80     Prime(x);

 81     ans = 0;

 82     t = (int) g.size();

 83     for (i = 1; i < (1 << t); i++) {

 84         tmp = Mul(i, j);

 85         if (j & 1)

 86             ans += x / tmp;

 87         else

 88             ans -= x / tmp;

 89     }

 90     return (x - ans) % P;

 91 }

 92 int main() {

 93     int c;

 94     int n, ans, i;

 95     Init();

 96     scanf("%d", &c);

 97     while (c--) {

 98         scanf("%d%d", &n, &P);

 99         Factor(n);

100         ans = 0;

101         for (i = 0; i < (int) fac.size(); i++) {

102             ans += PowMod(n, fac[i] - 1, P) * Count(n / fac[i]);

103             ans %= P;

104         }

105         printf("%d\n", ans);

106     }

107     return 0;

108 }

你可能感兴趣的:(color)