http://poj.org/problem?id=2888

题意: Harry Potter 要用m种颜色的珠子做一个长度为n的手镯,手镯首尾相接。其中某些颜色的珠子不兼容,不能放在一起。求Harry Potter能够早多少种不同的手镯(每种颜色的珠子都有无限多颗,旋转之后能够吻合的算同一种)。

解法:polya计数,sum = sigma ( Euler( n / i )*Gettr( i ) ) / n    { i | n }     主要是计算Gettr( i )的问题我们把m种颜色的关系画成一个无向图,而Gettr(i)就是长度为 i 的回路的个数把无向图表示成邻接矩阵 G[maxn][maxn],Gettr(i)就是这个矩阵的 i 次幂的迹,也就是 Trace(G^i),G^i 可以用快速幂来求,可以先把 G^1 G^2 G^4 ... G^(2^31) 先预处理出来,加速快速幂的过程。

  1 #include  < cstdio >
  2 #include  < complex >
  3 #include  < cstdlib >
  4 #include  < iostream >
  5 #include  < cstring >
  6 #include  < string >
  7 #include  < algorithm >
  8 using   namespace  std;
  9
 10 const   int  maxn  =   11 ;
 11 const   int  maxm  =   32000 ;
 12 const   int  P  =   9973 ;
 13 int  vis[ maxm ], p[ maxm ];
 14 int  plen, flen;
 15 int  aa[  32  ], bb[  32  ];
 16 int  n, m, ans;
 17 int  M[  32  ][ maxn ][ maxn ];
 18 void  prime( )
 19 {
 20    int i, j, k;
 21    plen = 0;
 22    memset( vis, 0sizeof( vis ) );
 23    for( i = 2, k = 4; i < maxm; ++i, k += i + i - 1 )
 24    {
 25        if!vis[ i ] )
 26        {
 27            p[ plen++ ] = i;
 28            if( k < maxm ) for( j = k; j < maxm; j += i ) vis[ j ] = 1;
 29        }

 30    }

 31}

 32
 33 int  pow_mod(  int  a,  int  b,  int  c )
 34 {
 35    int ans = 1, d = a % c;
 36    while( b )
 37    {
 38        if( b & 1 ) ans = ans * d % c;
 39        d = d * d % c;
 40        b >>= 1;
 41    }

 42    return ans;
 43}

 44
 45 void  matrix_mul(  int  a[ ][ maxn ],  int  b[ ][ maxn ],  int  p )
 46 {
 47    int c[ maxn ][ maxn ];
 48    forint i = 0; i < m; i++ )
 49    {
 50        forint j = 0; j < m; j++ )
 51        {
 52            c[ i ][ j ] = 0;
 53            forint k = 0; k < m; k++ )
 54                c[ i ][ j ] += a[ i ][ k ] * b[ k ][ j ];
 55        }

 56    }

 57    forint i = 0; i < m; i++ )
 58        forint j = 0; j < m; j++ )
 59            a[ i ][ j ] = c[ i ][ j ] % p;
 60}

 61
 62 int  matrix_mod(  int  a[ ][ maxn ],  int  b,  int  c )
 63 {
 64    int ans[ maxn ][ maxn ];
 65    memset( ans, 0sizeof( ans ) );
 66    forint i = 0; i < m; i++ ) ans[ i ][ i ] = 1;
 67    int j = 0;
 68    while( b )
 69    {
 70        if( b & 1 ) matrix_mul( ans, M[ j ], c );
 71        b >>= 1;
 72        j++;
 73    }

 74    int sum = 0;
 75    forint i = 0; i < m; i++ )
 76        sum = ( sum + ans[ i ][ i ] ) % c;
 77    return sum;
 78}

 79
 80 void  factor(  int  n )
 81 {
 82    flen = 0;
 83    forint i = 0; p[ i ] * p[ i ] <= n; i++ )
 84    {
 85        if( n % p[ i ] == 0 )
 86        {
 87            for( bb[ flen ] = 0; n % p[ i ] == 0++bb[ flen ], n /= p[ i ] );
 88            aa[ flen++ ] = p[ i ];
 89        }

 90    }

 91    if( n > 1 ) bb[ flen ] = 1, aa[ flen++ ] = n;
 92}
 
 93
 94 int  elur(  int  n )
 95 {
 96    int phi = n;
 97    forint i = 0; p[ i ] * p[ i ] <= n; i++ )
 98    {
 99        if( n % p[ i ] == 0 )
100        {
101            while( n % p[ i ] == 0 ) n /= p[ i ];
102            phi -= phi / p[ i ];
103        }

104    }

105    if( n > 1 ) phi -= phi / n;
106    return phi;
107}

108
109 int  inv(  int  n,  int  p )
110 {
111    return pow_mod( n, elur( p ) - 1, p );
112}

113
114 int  e[ maxn ][ maxn ], g[ maxn ][ maxn ];
115
116 void  init(  int  c )
117 {
118    forint i = 0; i < m; i++ )
119        forint j = 0; j < m; j++ )
120            M[ 0 ][ i ][ j ] = g[ i ][ j ];
121    forint i = 1; i < 32; i++ )
122    {
123        forint j = 0; j < m; j++ )
124        {
125            forint k = 0; k < m; k++ )
126            {
127                M[ i ][ j ][ k ] = 0;
128                forint l = 0; l < m; l++ )
129                    M[ i ][ j ][ k ] += M[ i - 1 ][ j ][ l ] * M[ i - 1 ][ l ][ k ];
130                M[ i ][ j ][ k ] %= c;
131            }

132        }

133    }

134}

135
136 void  DFS(  int  dep,  int  sum )
137 {
138    if( dep == flen )
139    {
140        forint i = 0; i < m; i++ )
141            forint j = 0; j < m; j++ )
142                e[ i ][ j ] = g[ i ][ j ];
143        ans = ( ans + elur( n / sum ) % P * matrix_mod( e, sum, P ) % P ) % P;
144        return;
145    }

146    forint tmp = 1, i = 0; i <= bb[ dep ]; tmp *= aa[ dep ], i++ )
147        DFS( dep + 1, sum * tmp );
148}

149
150 int  main( int  argc,  char   * argv[])
151 {
152    int k, x, y, cas;
153    prime( );
154    scanf( "%d"&cas );
155    while( cas-- )
156    {
157        scanf( "%d %d %d"&n, &m, &k );
158        forint i = 0; i < m; i++ )
159            forint j = 0; j < m; j++ )
160                g[ i ][ j ] = 1;
161        forint i = 0; i < k; i++ )
162        {
163            scanf( "%d %d"&x, &y );
164            g[ x - 1 ][ y - 1 ] = g[ y - 1 ][ x - 1 ] = 0;
165        }

166        init( P );
167        factor( n );
168        ans = 0;
169        DFS( 01 );
170        ans = ans * inv( n, P ) % P;
171        printf( "%d\n", ans ); 
172    }

173    return 0;
174}

175