题意:给出A和C(1<=A,C<=10^9),所有满足B * B * K + 1 = A * A, (K >= 0)的B,构成边长为B的正方形,等角度的围绕在一个小正方形的周围。用C种颜色着色,边长为B的正方形旋转后相同视为相同的方案,整个图形绕中间的小正方形旋转后相同也视为相同的着色方案,求着色方案数。
整体思路是:
首先,忽略中间的小正方形,得到所有的B,求边长为B的着色的方案数X。
其次,将每个B看成一个点,求用X种颜色对一个环着色的方案数。
最后,将答案乘以C。
要得到所有的B。由于A*A达10^18次方,根号n的复杂度寻找B肯定行不通。观察到B*B*K=A*A-1=(A+1)*(A-1)。
因此,分别对A+1和A-1分解质因子。
通过DFS枚举质因子得到B的值,同时剩下的质因子是K的。
再通过一个DFS对剩下的质因子枚举出K的约数即可。
对正方形着色:【HDU】1812 Count the Tetris
对环着色:【POJ】2154 Color
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #define MAXN 32000 5 #define P 1000000007 6 typedef long long LL; 7 using namespace std; 8 bool p[MAXN], flag1, flag2; 9 LL A, B, C, K; 10 LL ans1, ans2; 11 int depth1, depth2; 12 int prime[MAXN], factor[MAXN]; 13 int prime_size, factor_size, prifac_size; 14 struct node { 15 int val, cnt; 16 } prifac[MAXN]; 17 void Init() { 18 int i, j; 19 memset(p, true, sizeof(p)); 20 for (i = 2; i < 180; i++) { 21 if (p[i]) { 22 for (j = i * i; j < MAXN; j += i) 23 p[j] = false; 24 } 25 } 26 prime_size = 0; 27 for (i = 2; i < MAXN; i++) { 28 if (p[i]) 29 prime[prime_size++] = i; 30 } 31 } 32 void Factor(int x) { 33 int i; 34 for (i = 0; prime[i] * prime[i] <= x; i++) { 35 while (x % prime[i] == 0) { 36 factor[factor_size++] = prime[i]; 37 x /= prime[i]; 38 } 39 } 40 if (x > 1) 41 factor[factor_size++] = x; 42 } 43 LL Pow(LL a, LL b) { 44 LL ans; 45 for (ans = 1; b; b >>= 1) { 46 if (b & 1) 47 ans *= a; 48 a *= a; 49 } 50 return ans; 51 } 52 LL PowMod(LL a, LL b, LL c) { 53 LL ans; 54 a %= c; 55 for (ans = 1; b; b >>= 1) { 56 if (b & 1) { 57 ans *= a; 58 ans %= c; 59 } 60 a *= a; 61 a %= c; 62 } 63 return ans; 64 } 65 LL ExtGcd(LL a, LL b, LL &x, LL &y) { 66 LL t, d; 67 if (b == 0) { 68 x = 1; 69 y = 0; 70 return a; 71 } 72 d = ExtGcd(b, a % b, x, y); 73 t = x; 74 x = y; 75 y = t - a / b * y; 76 return d; 77 } 78 LL InvMod(LL a, LL n) { 79 LL x, y; 80 ExtGcd(a, n, x, y); 81 return (x % n + n) % n; 82 } 83 LL Count1(LL n) { 84 LL ans; 85 if (n & 1) 86 ans = (n - 1) * (n / 2 + 1) / 2 + 1; 87 else 88 ans = (n / 2) * (n / 2); 89 return ans; 90 } 91 LL Count2(LL n) { 92 LL ans; 93 if (n & 1) 94 ans = (n + 1) * (n - 1) / 2 + 1; 95 else 96 ans = n * n / 2; 97 return ans; 98 } 99 LL Square(LL x, LL k) { 100 LL ans; 101 ans = PowMod(k, x * x, P); 102 ans += PowMod(k, Count1(x), P) * 2 % P; 103 if (ans >= P) 104 ans -= P; 105 ans += PowMod(k, Count2(x), P); 106 if (ans >= P) 107 ans -= P; 108 return ans * InvMod(4, P) % P; 109 } 110 LL Phi(LL x) { 111 int i; 112 LL res; 113 res = x; 114 for (i = 0; i < prifac_size; i++) { 115 if (prifac[i].cnt && x % prifac[i].val == 0) 116 res -= res / prifac[i].val; 117 } 118 return res % P; 119 } 120 void Find(int now, int index, LL res, LL color) { 121 if (now == depth2) { 122 flag2 = true; 123 ans2 += PowMod(color, res, P) * Phi(K / res) % P; 124 if (ans2 >= P) 125 ans2 -= P; 126 } else { 127 int i, j; 128 for (i = index; i < prifac_size; i++) { 129 for (j = 1; j <= prifac[i].cnt; j++) 130 Find(now + 1, i + 1, 131 res * Pow(prifac[i].val, j), 132 color); 133 } 134 } 135 } 136 LL Burnside(LL n, LL k) { 137 ans2 = 0; 138 for (depth2 = 0;; depth2++) { 139 flag2 = false; 140 Find(0, 0, 1, k); 141 if (!flag2) 142 break; 143 } 144 return ans2 * InvMod(n, P) % P; 145 } 146 void DFS(int now, int index, LL res) { 147 if (now == depth1) { 148 flag1 = true; 149 B = res; 150 K = (A - 1) * (A + 1) / (B * B); 151 ans1 += Burnside(K, Square(B, C)); 152 if (ans1 >= P) 153 ans1 -= P; 154 } else { 155 LL tmp; 156 int i, j; 157 for (i = index; i < prifac_size; i++) { 158 for (j = 2; j <= prifac[i].cnt; j += 2) { 159 prifac[i].cnt -= j; 160 tmp = res * Pow(prifac[i].val, j >> 1); 161 DFS(now + 1, i + 1, tmp); 162 prifac[i].cnt += j; 163 } 164 } 165 } 166 } 167 LL Cal() { 168 int i, j; 169 factor_size = prifac_size = 0; 170 Factor(A - 1); 171 Factor(A + 1); 172 sort(factor, factor + factor_size); 173 for (i = 0; i < factor_size; i = j) { 174 prifac[prifac_size].val = factor[i]; 175 prifac[prifac_size].cnt = 0; 176 for (j = i; j < factor_size && factor[i] == factor[j]; j++) 177 prifac[prifac_size].cnt++; 178 prifac_size++; 179 } 180 ans1 = 0; 181 for (depth1 = 0;; depth1++) { 182 flag1 = false; 183 DFS(0, 0, 1); 184 if (!flag1) 185 break; 186 } 187 return ans1 * C % P; 188 } 189 int main() { 190 int c, ca = 1; 191 LL ans; 192 Init(); 193 scanf("%d", &c); 194 while (c--) { 195 scanf("%lld%lld", &A, &C); 196 if (A == 1) 197 ans = C; 198 else 199 ans = Cal(); 200 printf("Case %d: %lld\n", ca++, ans); 201 } 202 return 0; 203 }