题意:给出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 }
posted on 2012-09-15 20:40  DrunBee  阅读(696)  评论(0编辑  收藏  举报