代码改变世界

hdu 1812

2016-04-17 12:43  koujiao的蒻苣  阅读(308)  评论(0编辑  收藏  举报

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


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

标准的polya定理问题。Polya定理,公式:S=(C^M1+C^M2+...+C^Mn)/G
G是阶数,Mi是各阶循环节的个数。

旋转只有 0,90,180,270度三种旋法。

旋0度,则置换的轮换数为n*n
旋90度,n为偶数时,则置换的轮换数为n*n/4,n为奇数,则置换的轮换数为(n*n-1)/4+1
旋180度,n为偶数时,则置换的轮换数为n*n/2,n为奇数,则置换的轮换数为(n*n-1)/2+1
旋270度,n为偶数时,则置换的轮换数为n*n/4,n为奇数,则置换的轮换数为(n*n-1)/4+1

反射 沿对角反射两种,沿对边中点连线反射两种
n为偶数时,沿对边中点连线反射两种的置换轮换数为 n*n/2
                     沿对角反射两种的置换轮换数为 (n*n-n)/2+n
n为奇数时,沿对边中点连线反射两种的置换轮换数为 (n*n-n)/2+n
                     沿对角反射两种的置换轮换数为 (n*n-n)/2+n

代码:

#include<cstdio>
#include <cassert>
#include<cstring>
#include<algorithm>
using namespace std;
const int MOD=10000;
const int B=10000;
const int SIZEN=505;
const int L=505;
struct Mat{
    int num[40][40];
    void init(int n){
        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++)
            num[i][j]=i*n+j;
    }
    void change(int n){
        int t_num[40][40];
        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++) t_num[j][n-i-1]=num[i][j];
        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++) num[i][j]=t_num[i][j];
    }
    void change1(int n){
        int t_num[40][40];
        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++) t_num[i][n-j-1]=num[i][j];
        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++) num[i][j]=t_num[i][j];
    }
    void change2(int n){
        int t_num[40][40];
        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++) t_num[n-i-1][j]=num[i][j];
        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++) num[i][j]=t_num[i][j];
    }
    void change3(int n){
        int t_num[40][40];
        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++) t_num[j][i]=num[i][j];
        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++) num[i][j]=t_num[i][j];
    }
    void change4(int n){
        int t_num[40][40];
        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++) t_num[n-1-j][n-1-i]=num[i][j];
        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++) num[i][j]=t_num[i][j];
    }
    void output(int n){
        for(int i=0;i<n;i++){
            for(int j=0;j<n;j++) printf("%d ",num[i][j]);
            printf("\n");
        }
    }
};
struct BigInteger {
    BigInteger(int number = 0) : length(!!number) {
        assert(0 <= number && number < B);
        memset(digit, 0, sizeof(digit));
        digit[0] = number;
    }

    BigInteger normalize() {
        while (length && !digit[length - 1]) {
            length --;
        }
        return *this;
    }

    int operator[](int index) const {
        return digit[index];
    }

    int& operator[](int index) {
        return digit[index];
    }

    void output(){
        printf("%d",digit[length-1]);
        for(int i=length-2;i>=0;i--) printf("%04d",digit[i]);
        printf("\n");
    }

    int length, digit[L];
};

bool operator < (const BigInteger &a, const BigInteger &b)
{
    if (a.length != b.length) {
        return a.length < b.length;
    }
    for (int i = 0; i < a.length; ++ i) {
        if (a[i] != b[i]) {
            return a[i] < b[i];
        }
    }
    return false;
}

BigInteger operator + (const BigInteger &a, const BigInteger &b)
{
    BigInteger c;
    c.length = std::max(a.length, b.length) + 1;
    for (int i = 0, delta = 0; i < c.length; ++ i) {
        delta += a[i] + b[i];
        c[i] = delta % B;
        delta /= B;
    }
    return c.normalize();
}

BigInteger operator - (const BigInteger &a, int b)
{
    assert(0 <= b && b < B);
    BigInteger c;
    c.length = a.length;
    for (int i = 0, delta = -b; i < a.length; ++ i) {
        delta += a[i];
        c[i] = delta;
        delta = 0;
        if (c[i] < 0) {
            c[i] += B;
            delta = -1;
        }
    }
    return c.normalize();
}

BigInteger operator * (const BigInteger &a, const BigInteger &b)
{
    BigInteger c;
    c.length = a.length + b.length;
    for (int i = 0; i < a.length; ++ i) {
        for (int j = 0, delta = 0; j <= b.length; ++ j) {
            delta += a[i] * b[j] + c[i + j];
            c[i + j] = delta % B;
            delta /= B;
        }
    }
    return c.normalize();
}

BigInteger operator / (const BigInteger &a, int b)
{
    assert(0 <= b && b < B);
    BigInteger c;
    c.length = a.length;
    for (int i = c.length - 1, delta = 0; i >= 0; -- i) {
        delta = delta * B + a[i];
        c[i] = delta / b;
        delta %= b;
    }
    return c.normalize();
}
BigInteger operator ^(const BigInteger &a,int b){
    BigInteger ret,ta;
    ret=1;ta=a;
    while(b){
        if(b&1) ret=ret*ta;
        ta=ta*ta;
        b>>=1;
    }
    return ret;
}
Mat mat;
BigInteger ret,tmp;
bool vis[1005];
void dfs(int u,int n){
    if(vis[u]) return;
    vis[u]=1;
    int x=u/n;
    int y=u%n;
    dfs(mat.num[x][y],n);
}
void solve(int n,int c){
    ret=0;
    ret.normalize();
    tmp=c;
    tmp.normalize();
    if(n%2==0){
        ret=ret+(tmp^(n*n));
        ret=ret+(tmp^(n*n/4));
        ret=ret+(tmp^(n*n/2));
        ret=ret+(tmp^(n*n/4));
        ret=ret+(tmp^(n*n/2))*2;
        ret=ret+(tmp^((n*n-n)/2+n))*2;
    }
    else{
        ret=ret+(tmp^(n*n));
        ret=ret+(tmp^(n*n-1)/4+1);
        ret=ret+(tmp^(n*n-1)/2+1);
        ret=ret+(tmp^(n*n-1)/4+1);
        ret=ret+(tmp^((n*n-n)/2+n))*2;
        ret=ret+(tmp^((n*n-n)/2+n))*2;
    }
    ret=ret/8;
    ret.output();
}
int main()
{
    int n,c;
    while(scanf("%d%d",&n,&c)!=EOF)
        solve(n,c);
}