【HDU】4187 Alphabet Soup

题意:一个圆上有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 }

你可能感兴趣的:(Alpha)