【HDU】3441 Rotation

题意:给出A和C(1<=A,C<=10^9),所有满足B * B * K + 1 = A * A, (K >= 0)的B,构成边长为B的正方形,等角度的围绕在一个小正方形的周围。用C种颜色着色,边长为B的正方形旋转后相同视为相同的方案,整个图形绕中间的小正方形旋转后相同也视为相同的着色方案,求着色方案数。

【HDU】3441 Rotation

整体思路是:

首先,忽略中间的小正方形,得到所有的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 }

你可能感兴趣的:(HDU)