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) 先预处理出来,加速快速幂的过程。
题意: 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, 0, sizeof( 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
for( int i = 0; i < m; i++ )
49
{
50
for( int j = 0; j < m; j++ )
51
{
52
c[ i ][ j ] = 0;
53
for( int k = 0; k < m; k++ )
54
c[ i ][ j ] += a[ i ][ k ] * b[ k ][ j ];
55
}
56
}
57
for( int i = 0; i < m; i++ )
58
for( int 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, 0, sizeof( ans ) );
66
for( int 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
for( int 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
for( int 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
for( int 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
for( int i = 0; i < m; i++ )
119
for( int j = 0; j < m; j++ )
120
M[ 0 ][ i ][ j ] = g[ i ][ j ];
121
for( int i = 1; i < 32; i++ )
122
{
123
for( int j = 0; j < m; j++ )
124
{
125
for( int k = 0; k < m; k++ )
126
{
127
M[ i ][ j ][ k ] = 0;
128
for( int 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
for( int i = 0; i < m; i++ )
141
for( int 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
for( int 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
for( int i = 0; i < m; i++ )
159
for( int j = 0; j < m; j++ )
160
g[ i ][ j ] = 1;
161
for( int 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( 0, 1 );
170
ans = ans * inv( n, P ) % P;
171
printf( "%d\n", ans );
172
}
173
return 0;
174
}
175

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19



20

21

22

23

24



25

26



27

28

29

30

31

32

33

34



35

36

37



38

39

40

41

42

43

44

45

46



47

48

49



50

51



52

53

54

55

56

57

58

59

60

61

62

63



64

65

66

67

68

69



70

71

72

73

74

75

76

77

78

79

80

81



82

83

84



85

86



87

88

89

90

91

92

93

94

95



96

97

98



99

100



101

102

103

104

105

106

107

108

109

110



111

112

113

114

115

116

117



118

119

120

121

122



123

124



125

126



127

128

129

130

131

132

133

134

135

136

137



138

139



140

141

142

143

144

145

146

147

148

149

150

151



152

153

154

155

156



157

158

159

160

161

162



163

164

165

166

167

168

169

170

171

172

173

174

175
