题意:
给出种颜色的球的个数,现在要将全部的球拼成一个环,有多少种拼发。
题解:
分成两种情况,1、翻折;2、旋转。
1、翻折。要分奇数和偶数,奇数只有一种翻折方法就是定点和边中点连线为轴转,偶数即可是定点和定点也可以是边和边。
2、旋转。每种旋转循环节长度都是能被环的长度整数的,因此只要找到循环节的个数(gcd(n,i)),长度就可以计算出来了。
注意数据量,要用高精度。
#include<iostream>
#include<math.h>
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<vector>
#include<queue>
#include<map>
#include<set>
#define B(x) (1<<(x))
using namespace std;
typedef long long ll;
void cmax(int& a,int b){ if(b>a)a=b; }
void cmin(int& a,int b){ if(b<a)a=b; }
void cmax(ll& a,ll b){ if(b>a)a=b; }
void cmin(ll& a,ll b){ if(b<a)a=b; }
void add(int& a,int b,int mod){ a=(a+b)%mod; }
void add(ll& a,ll b,ll mod){ a=(a+b)%mod; }
const int oo=0x3f3f3f3f;
const ll MOD=1000000007;
#define MAXN 9999
#define MAXSIZE 10
#define DLEN 4
class BigNum
{
private:
int a[500]; //可以控制大数的位数
int len; //大数长度
public:
BigNum(){ len = 1;memset(a,0,sizeof(a)); }
BigNum(const int);
BigNum(const char*);
BigNum(const BigNum &);
BigNum &operator=(const BigNum &);
friend istream& operator>>(istream&, BigNum&);
friend ostream& operator<<(ostream&, BigNum&);
BigNum operator+(const BigNum &) const;
BigNum operator*(const BigNum &) const;
BigNum operator/(const int &) const;
void print(); //输出大数
};
BigNum::BigNum(const int b) //将一个int类型的变量转化为大数
{
int c,d = b;
len = 0;
memset(a,0,sizeof(a));
while(d > MAXN)
{
c = d - (d / (MAXN + 1)) * (MAXN + 1);
d = d / (MAXN + 1);
a[len++] = c;
}
a[len++] = d;
}
BigNum::BigNum(const char*s) //将一个字符串类型的变量转化为大数
{
int t,k,index,l,i;
memset(a,0,sizeof(a));
l=strlen(s);
len=l/DLEN;
if(l%DLEN)
len++;
index=0;
for(i=l-1;i>=0;i-=DLEN)
{
t=0;
k=i-DLEN+1;
if(k<0)
k=0;
for(int j=k;j<=i;j++)
t=t*10+s[j]-'0';
a[index++]=t;
}
}
BigNum::BigNum(const BigNum & T) : len(T.len) //拷贝构造函数
{
int i;
memset(a,0,sizeof(a));
for(i = 0 ; i < len ; i++)
a[i] = T.a[i];
}
BigNum & BigNum::operator=(const BigNum & n) //重载赋值运算符,大数之间进行赋值运算
{
int i;
len = n.len;
memset(a,0,sizeof(a));
for(i = 0 ; i < len ; i++)
a[i] = n.a[i];
return *this;
}
BigNum BigNum::operator+(const BigNum & T) const //两个大数之间的相加运算
{
BigNum t(*this);
int i,big; //位数
big = T.len > len ? T.len : len;
for(i = 0 ; i < big ; i++)
{
t.a[i] +=T.a[i];
if(t.a[i] > MAXN)
{
t.a[i + 1]++;
t.a[i] -=MAXN+1;
}
}
if(t.a[big] != 0)
t.len = big + 1;
else
t.len = big;
return t;
}
BigNum BigNum::operator*(const BigNum & T) const //两个大数之间的相乘运算
{
BigNum ret;
int i,j,up;
int temp,temp1;
for(i = 0 ; i < len ; i++)
{
up = 0;
for(j = 0 ; j < T.len ; j++)
{
temp = a[i] * T.a[j] + ret.a[i + j] + up;
if(temp > MAXN)
{
temp1 = temp - temp / (MAXN + 1) * (MAXN + 1);
up = temp / (MAXN + 1);
ret.a[i + j] = temp1;
}
else
{
up = 0;
ret.a[i + j] = temp;
}
}
if(up != 0)
ret.a[i + j] = up;
}
ret.len = i + j;
while(ret.a[ret.len - 1] == 0 && ret.len > 1)
ret.len--;
return ret;
}
BigNum BigNum::operator/(const int & b) const
{
BigNum ret;
int i,down = 0;
for(i = len - 1 ; i >= 0 ; i--)
{
ret.a[i] = (a[i] + down * (MAXN + 1)) / b;
down = a[i] + down * (MAXN + 1) - ret.a[i] * b;
}
ret.len = len;
while(ret.a[ret.len - 1] == 0 && ret.len > 1)
ret.len--;
return ret;
}
void BigNum::print() //输出大数
{
int i;
cout << a[len - 1];
for(i = len - 2 ; i >= 0 ; i--)
{
cout.width(DLEN);
cout.fill('0');
cout << a[i];
}
cout << endl;
}
BigNum C[44][44];
int a[4],b[4];
int n;
void Init(){
for(int i=0;i<44;i++){
C[i][0]=1;
C[i][i]=1;
for(int j=1;j<i;j++)
C[i][j]=C[i-1][j-1]+C[i-1][j];
}
}
int gcd(int a,int b){
return b==0 ? a : gcd(b,a%b);
}
BigNum Count(int k){
int m=0;
for(int i=0;i<3;i++){
if(b[i]%k==0){
b[i]/=k;
m+=b[i];
}else return 0;
}
BigNum sum=1;
for(int i=0;i<3;i++){
sum=sum*C[m][b[i]];
m-=b[i];
}
return sum;
}
BigNum Rotate(){
BigNum ans=0;
memcpy(b,a,sizeof a);
ans=ans+Count(1);//旋转0度
for(int i=1;i<n;i++){
int cnt=gcd(n,i);
memcpy(b,a,sizeof a);
ans=ans+Count(n/cnt);
}
return ans;
}
BigNum Flippy(){
BigNum ans=0;
if(n&1){
for(int i=0;i<3;i++){
memcpy(b,a,sizeof a);
b[i]--;
if(b[i]<0)continue;
ans=ans+Count(2)*n;
}
}else{
for(int i=0;i<3;i++){
for(int j=0;j<3;j++){
memcpy(b,a,sizeof a);
b[i]--;b[j]--;
if(b[i]<0||b[j]<0)continue;
ans=ans+Count(2)*(n/2);
}
}
memcpy(b,a,sizeof a);
ans=ans+Count(2)*(n/2);
}
return ans;
}
BigNum Polya(){
BigNum ans=0;
ans=ans+Rotate();
ans=ans+Flippy();
return ans/(n*2);
}
int main()
{
//freopen("E:\\read.txt","r",stdin);
int T,col;
Init();
scanf("%d",&T);
while(T--){
n=0;
for(int i=0;i<3;i++){
scanf("%d",&a[i]);
n+=a[i];
}
Polya().print();
}
return 0;
}
/*
2
3 2 1
2 2 2
*/