zoukankan      html  css  js  c++  java
  • 【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 }
  • 相关阅读:
    【HNOI 2002】 营业额统计
    【BZOJ 3224】 普通平衡树
    【NOIP2014】 联合权值
    【NOIP2016】 组合数问题
    BZOJ2212 POI2011Tree Rotations(线段树合并)
    LOJ114 k大(xiao)异或和(线性基)
    LOJ121 动态图连通性(LCT)
    BZOJ3569 DZY Loves Chinese II(随机化+树上差分+线性基)
    BZOJ3237 AHOI2013连通图(线段树分治+并查集)
    BZOJ2208 JSOI2010连通数(floyd+bitset)
  • 原文地址:https://www.cnblogs.com/DrunBee/p/2684196.html
Copyright © 2011-2022 走看看