见上方链接.
-
先考虑 旋转同构,
设顺时针旋转 个, 共有 个循环节, 每个循环节的长度都为 ,
要成功染色, 必须满足 才可以成功染色,
将 同时除 ,
染色的方案数 为 , -
再考虑 对称同构,
1.若 为 奇数,- 颜色必须为 , 否则无解.
- 若满足上述条件, 则设 为奇数, 将 减 后, 三者除 ,
方案数 为 .
2.若 为 偶数,
- 对称轴穿过两个点,
- 两奇一偶,
将两个奇数减去 , 三者除, 方案数 为 . - 全部为偶数, 三者除, 方案数为 .
- 两奇一偶,
- 对称轴不过点,要满足 均为偶数
将 全部除 , 方案数 为
将所有方案加起来后 除 总置换数 即可.
#include<cstdio>
#define reg register
typedef long long ll;
int a, a1;
int b, b1;
int c, c1;
int N;
ll C[50][50];
int gcd(int a, int b){ return !b?a:gcd(b, a%b); }
ll Calc(){ return C[a1+b1+c1][a1] * C[b1+c1][b1]; }
void Init(){
C[0][0] = 1;
reg int j;
for(reg int i = 1; i <= 45; i ++)
for(j = 1, C[i][0]=1; j <= i; j ++) C[i][j] = C[i-1][j] + C[i-1][j-1];
}
void Work(){
scanf("%d%d%d", &a, &b, &c);
N = a+b+c;
ll Ans = 0;
for(reg int k = 0; k < N; k ++){
int size = N/gcd(k, N);
if(a%size || b%size || c%size) continue ;
a1 = a/size, b1 = b/size, c1 = c/size;
Ans += Calc();
}
if(N & 1){
int cnt = (a&1) + (b&1) + (c&1);
if(cnt == 1){
if(a & 1) a1 = a-1>>1, b1 = b>>1, c1 = c>>1;
else if(b & 1) a1 = a>>1, b1 = b-1>>1, c1=c>>1;
else a1 = a>>1, b1 = b>>1, c1 = c-1>>1;
Ans += N * Calc();
}
}else{
int cnt = (a&1) + (b&1) + (c&1);
if(!cnt){
a1 = a>>1, b1 = b>>1, c1 = c>>1;
Ans += N*Calc();
}else if(cnt == 2){
if(a%2 == 0) a1 = a>>1, b1 = b-1>>1, c1 = c-1>>1;
else if(b%2 == 0) a1 = a-1>>1, b1 = b>>1, c1 = c-1>>1;
else a1 = a-1>>1, b1 = b-1>>1, c1 = c>>1;
Ans += N*Calc();
}
}
printf("%lld
", Ans/2/N);
}
int main(){
Init();
int T;
scanf("%d", &T);
while(T --) Work();
return 0;
}