hdu 1812

大数模板+Polya定理

Count the Tetris

Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 2681    Accepted Submission(s): 752


Problem Description
话说就是因为这个游戏,Lele已经变成一个名人,每当他一出现在公共场合,就有无数人找他签名,挑战。

为了防止引起社会的骚动,Lele决定还是乖乖呆在家里。

在家很无聊,Lele可不想像其他人一样每天没事在家数钱玩,于是他就开始数棋盘。他想知道,一个有N×N个格子的正方形棋盘,每个格子可以用C种不同颜色来染色,一共可以得到多少种不同的棋盘。如果一个棋盘,经过任意旋转,反射后变成另一个棋盘,这两个棋盘就是属于同一种棋盘。

比如当N=C=2的时候,有下面六种不同的棋盘



现在告诉你N和C,请你帮帮Lele算算,到底有多少种不同的棋盘
 

Input
本题目包含多组测试,请处理到文件结束。
每组测试数据包含两个正整数N和C(0<N,C,<31),分别表示棋盘的大小是N×N,用C种颜色来进行染色。
 

Output
对于每组测试,在一行里输出答案。
 

Sample Input
  
  
2 2 3 1
 

Sample Output
  
  
6 1
 

Author
linle

#include"bits/stdc++.h"
using namespace std;
typedef unsigned long long LL;
const int MX = 355;
const int MAXN = 9999;
const int DLEN = 4;
class Big
{
public:
    int a[MX], len;
    Big(const int b = 0)
    {
        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;
    }
    Big(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;
        }
    }
    Big operator/(const int &b)const
    {
        Big ret;
        int i, down = 0;
        for(int 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;
    }
    bool operator>(const Big &T)const
    {
        int ln;
        if(len > T.len) return true;
        else if(len == T.len)
        {
            ln = len - 1;
            while(a[ln] == T.a[ln] && ln >= 0) ln--;
            if(ln >= 0 && a[ln] > T.a[ln]) return true;
            else return false;
        }
        else return false;
    }
    Big operator+(const Big &T)const
    {
        Big 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;
    }
    Big operator-(const Big &T)const
    {
        int i, j, big;
        bool flag;
        Big t1, t2;
        if(*this > T)
        {
            t1 = *this;
            t2 = T;
            flag = 0;
        }
        else
        {
            t1 = T;
            t2 = *this;
            flag = 1;
        }
        big = t1.len;
        for(i = 0; i < big; i++)
        {
            if(t1.a[i] < t2.a[i])
            {
                j = i + 1;

                while(t1.a[j] == 0) j++;
                t1.a[j--]--;
                while(j > i) t1.a[j--] += MAXN;
                t1.a[i] += MAXN + 1 - t2.a[i];
            }
            else t1.a[i] -= t2.a[i];
        }
        t1.len = big;
        while(t1.a[t1.len - 1] == 0 && t1.len > 1)
        {
            t1.len--;
            big--;
        }
        if(flag) t1.a[big - 1] = 0 - t1.a[big - 1];
        return t1;
    }
    int operator%(const int &b)const
    {
        int i, d = 0;
        for(int i = len - 1; i >= 0; i--)
        {
            d = ((d * (MAXN + 1)) % b + a[i]) % b;
        }
        return d;
    }
    Big operator*(const Big &T) const
    {
        Big ret;
        int i, j, up, 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;
    }
    void print()
    {
        printf("%d", a[len - 1]);
        for(int i = len - 2; i >= 0; i--) printf("%04d", a[i]);
    }
};

Big ans,ret;
void work(int m,int nn){
    Big a = m;
    while(nn){
        if(nn&1) ret = ret*a;
        a = a*a;
        nn >>= 1;
    }
    ans = ans+ret;
}

int main()
{
    int n,m;
    while(~scanf("%d%d",&n,&m))
    {
        ans = 0;
        int nn = n*n;
        ret = 1;
        work(m,nn);

        if(n&1){
            ret = 2;
            work(m,nn/4+1);

            ret = 1;
            work(m,nn/2+1);

            ret = 4;
            work(m,n+(nn-n)/2);
        }
        else{
            ret = 2;
            work(m,nn/4);

            ret = 3;
            work(m,nn/2);

            ret = 2;
            work(m,n+(nn-n)/2);
        }
        ans = ans/8;
        ans.print();
        puts("");
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值