uva 11255 Necklace (polya)

题意:

给出种颜色的球的个数,现在要将全部的球拼成一个环,有多少种拼发。

题解:

分成两种情况,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
*/



你可能感兴趣的:(uva 11255 Necklace (polya))