题意:一个圆上有n个点,用不同的角度表示,用k种颜色对n个点着色,旋转后相同视为同一种着色方案,问着色方案数。

举几个例子:

0 90000 180000 270000,每次旋转90度,每个点都能重合。

0 45000 90000 180000 270000,无论怎么旋转,都不能重合。

30000 150000 180000 330000,旋转180度才能重合。

如何判断在旋转360度之内,能重合几次。

将两个连续的点之间的角度差值处理出来,最多循环t次,那么有t个旋转使得重合。这可以用到next数组的性质。

设当前得到a个循环,每个循环b个点。

那么可以把b个点看成一个点,那么问题转化为a个点构成的环,着k^b种颜色,旋转后相同视为同一种着色方案,问着色方案数。

就和这题等价了:【POJ】2154 Color

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<vector>
  4 #include<algorithm>
  5 #define MAXN 360010
  6 #define S 360000
  7 #define P 100000007
  8 typedef long long LL;
  9 using namespace std;
 10 int dg[MAXN], str[MAXN], next[MAXN], phi[MAXN];
 11 vector<int> factor;
 12 LL PowMod(LL a, LL b, LL c) {
 13     LL ans;
 14     a %= c;
 15     for (ans = 1; b; b >>= 1) {
 16         if (b & 1) {
 17             ans *= a;
 18             ans %= c;
 19         }
 20         a *= a;
 21         a %= c;
 22     }
 23     return ans;
 24 }
 25 int NEXT(int n) {
 26     int i, j;
 27     next[0] = j = -1;
 28     for (i = 0; i < n;) {
 29         if (j < 0 || str[i] == str[j]) {
 30             i++;
 31             j++;
 32             next[i] = j;
 33         } else
 34             j = next[j];
 35     }
 36     i = n - j;
 37     if (n % i)
 38         return n;
 39     return i;
 40 }
 41 LL ExtGcd(LL a, LL b, LL &x, LL &y) {
 42     LL t, d;
 43     if (b == 0) {
 44         x = 1;
 45         y = 0;
 46         return a;
 47     }
 48     d = ExtGcd(b, a % b, x, y);
 49     t = x;
 50     x = y;
 51     y = t - a / b * y;
 52     return d;
 53 }
 54 LL InvMod(LL a, LL n) {
 55     LL x, y;
 56     ExtGcd(a, n, x, y);
 57     return (x % n + n) % n;
 58 }
 59 void Factor(int n) {
 60     int i;
 61     factor.clear();
 62     for (i = 1; i * i <= n; i++) {
 63         if (n % i == 0) {
 64             factor.push_back(i);
 65             if (i * i == n)
 66                 continue;
 67             factor.push_back(n / i);
 68         }
 69     }
 70 }
 71 LL Burnside(int n, int k) {
 72     int i;
 73     LL ans;
 74     Factor(n);
 75     for (ans = i = 0; i < (int) factor.size(); i++) {
 76         ans += PowMod(k, factor[i], P) * phi[n / factor[i]] % P;
 77         if (ans >= P)
 78             ans -= P;
 79     }
 80     return (ans * InvMod(n, P)) % P;
 81 }
 82 void Init() {
 83     int i, j;
 84     memset(phi, 0, sizeof(phi));
 85     phi[1] = 1;
 86     for (i = 2; i < MAXN; i++) {
 87         if (!phi[i]) {
 88             for (j = i; j < MAXN; j += i) {
 89                 if (!phi[j])
 90                     phi[j] = j;
 91                 phi[j] -= phi[j] / i;
 92             }
 93         }
 94     }
 95 }
 96 int main() {
 97     int k, n, i, len;
 98     Init();
 99     while (scanf("%d%d", &k, &n), k != -1 || n != -1) {
100         for (i = 0; i < n; i++)
101             scanf("%d", &dg[i]);
102         sort(dg, dg + n);
103         for (i = 1; i < n; i++)
104             str[i] = dg[i] - dg[i - 1];
105         str[0] = S - dg[n - 1] + dg[0];
106         len = NEXT(n);
107         printf("%I64d\n", Burnside(n / len, PowMod(k, len, P)));
108     }
109     return 0;
110 }
posted on 2012-09-14 00:37  DrunBee  阅读(454)  评论(0编辑  收藏  举报