UVA_11255
应用burnside引理,关键在于对于每种置换求出不动方案的种数。
import java.math.BigInteger; import java.util.Scanner; public class Main { static int MAXD = 50; static Scanner cin = new Scanner(System.in); static int N, P, pn; static int[] a = new int[5], b = new int[5], prime = new int[MAXD], p = new int[MAXD]; static boolean[] isprime = new boolean[MAXD]; static BigInteger[] fac = new BigInteger[MAXD]; static BigInteger ans; public static void main(String[] args) { prepare(); int t = cin.nextInt(); while(t != 0) { -- t; init(); solve(); } } static void prepare() { int i, j, k = 40; fac[0] = fac[1] = new BigInteger("1"); for(i = 2; i <= k; i ++) fac[i] = fac[i - 1].multiply(BigInteger.valueOf(i)); for(i = 0; i <= k; i ++) isprime[i] = true; P = 0; for(i = 2; i <= k; i ++) if(isprime[i]) { prime[P ++] = i; for(j = i * i; j <= k; j += i) isprime[i] = false; } } static void init() { int i; N = 0; for(i = 0; i < 3; i ++) { a[i] = cin.nextInt(); N += a[i]; } divide(N); } static void divide(int n) { int i; pn = 0; for(i = 0; i < P && prime[i] * prime[i] <= n; i ++) if(n % prime[i] == 0) { p[pn ++] = prime[i]; while(n % prime[i] == 0) n /= prime[i]; } if(n > 1) p[pn ++] = n; } static int euler(int n) { int i, ans = n; for(i = 0; i < pn; i ++) if(n % p[i] == 0) ans = ans / p[i] * (p[i] - 1); return ans; } static void solve() { ans = new BigInteger("0"); dfs(0, 1, N); if(N % 2 == 1) { for(int i = 0; i < 3; i ++) { for(int j = 0; j < 3; j ++) b[j] = a[j]; -- b[i]; if(b[i] < 0) continue; ans = ans.add(calculate(2).multiply(BigInteger.valueOf(N))); } } else { for(int i = 0; i < 3; i ++) b[i] = a[i]; ans = ans.add(calculate(2).multiply(BigInteger.valueOf(N / 2))); for(int i = 0; i < 3; i ++) for(int j = 0; j < 3; j ++) { for(int k = 0; k < 3; k ++) b[k] = a[k]; -- b[i]; -- b[j]; if(b[i] < 0 || b[j] < 0) continue; ans = ans.add(calculate(2).multiply(BigInteger.valueOf(N / 2))); } } ans = ans.divide(BigInteger.valueOf(2 * N)); System.out.println(ans); } static BigInteger calculate(int m) { int i, n = 0; BigInteger ans = new BigInteger("1"); for(i = 0; i < 3; i ++) { if(b[i] % m != 0) return BigInteger.ZERO; b[i] /= m; n += b[i]; } for(i = 0; i < 3; i ++) { ans = ans.multiply(comb(n, b[i])); n -= b[i]; } return ans; } static void dfs(int cur, int v, int x) { int i, cnt = 0, t = 1; if(cur == pn) { for(i = 0; i < 3; i ++) b[i] = a[i]; ans = ans.add(calculate(N / v).multiply(BigInteger.valueOf(euler(N / v)))); return ; } while(x % p[cur] == 0) { ++ cnt; x /= p[cur]; } for(i = 0; i <= cnt; i ++) { dfs(cur + 1, v * t, x); t *= p[cur]; } } static BigInteger comb(int n, int m) { return fac[n].divide(fac[m]).divide(fac[n - m]); } }