前两天看了Polya定理,今天做了一道HDU的题,伤心了,超时。。。我的高精度超时。。。看了statistics,大部分是用JAVA过的。要好好学JAVA。。。
Problem Description
话说就是因为这个游戏,Lele已经变成一个名人,每当他一出现在公共场合,就有无数人找他签名,挑战。

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

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

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

HDU 1812  。。。Polya定理。。。超时有感。。。_第1张图片



现在告诉你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定理,公式:S=(C^M1+C^M2+...+C^Mn)/G
G是阶数,Mi是各阶循环节的个数。
根据题意,有旋转和翻转两种情况,G=8,旋转4,翻转4。
对于旋转,以2*2为例很容易知道有旋转90度,180度,270度和360度,循环分别为(1,2,3,4);(1,3)(2,4);(1,4,3,2);(1)(2)(3)(4).
翻转则是枚举对称轴,正方形又分为沿对角线和沿边的中垂线两种。
附超时代码。。。。计算结果是正确的。。。。。:
TLE_CODE
#include<iostream>
struct M
{
    
int m[3000];
};
using namespace std;
int n,cou;
M Add(M a,M b)
{
    M res;
    memset(res.m,
0,sizeof(res.m));
    res.m[
0]=a.m[0]>b.m[0]?a.m[0]:b.m[0];
    
int i;
    
int t=0;
    
for(i=1;i<=res.m[0];i++)
    {
        res.m[i]
=(a.m[i]+b.m[i]+t);
        t
=res.m[i]/10;
        res.m[i]
%=10;
    }
    
if(t)
    {
        res.m[
++res.m[0]]=t%10;
        t
/=10;
    }
    
return res;
}
M Mult(M a,M b)
{
    M res;
    memset(res.m,
0,sizeof(res.m));
    res.m[
0]=a.m[0]+b.m[0]-1;
    
int i,j;
    
for(i=1;i<=b.m[0];i++)
    {
        
int t=0;
        
for(j=1;j<=a.m[0];j++)
        {
            res.m[i
+j-1]+=a.m[j]*b.m[i]+t;
            t
=res.m[i+j-1]/10;
            res.m[i
+j-1]%=10;
        }
        
while(t)
        {
            res.m[i
+j-1]=t%10;
            t
/=10;
            
if(i+j-1>res.m[0])
                res.m[
0]=i+j-1;    
            j
++;
        }
    }
    
return res;
}
M Div(M a,
int b)
{
    
int i;
    
int left=0;
    M res;
    memset(res.m,
0,sizeof(res.m));
    res.m[
0]=a.m[0];
    
for(i=a.m[0];i>=1;i--)
    {
        left
=left*10+a.m[i];
        res.m[i]
=left/b;
        left
%=b;
    }
    
while(res.m[res.m[0]]==0&&res.m[0]>1)
        res.m[
0]--;
    
return res;
}
M pow(M a,
int n)
{
    M res;
    memset(res.m,
0,sizeof(res.m));
    res.m[
0]=res.m[1]=1;
    M x
=a;
    
while(1)
    {
        
if(n&1)
        {
            M tmp;
            tmp
=Mult(res,x);
            res
=tmp;
        }
        
if(n>>=1)
        {
            M tmp;
            tmp
=Mult(x,x);
            x
=tmp;
        }
        
else break;
    }
    
return res;
}
int main()
{
    
while(scanf("%d%d",&n,&cou)!=EOF)
    {
        M c;
        
int i;
        memset(c.m,
0,sizeof(c.m));
        
while(cou)
        {
            c.m[
++c.m[0]]=cou%10;
            cou
/=10;
        }
        M rot,
ref;
        
int num1=0;
        
if(n&1)
        {
            
int t=n;
            
while(t>1)
            {
                num1
+=(t-1);
                t
-=2;
            }
            M k;
            M tt;
            M q,qq,qqq,qqqq;
            k
=pow(c,num1);
            tt
=Mult(c,k);
            q
=Mult(k,k);
            qqq
=Mult(q,q);
            qq
=Mult(c,q);
            qqqq
=Mult(c,qqq);
            rot
=Add(Add(Add(tt,tt),qq),qqqq);
        }
        
else 
        {    
            num1
=n*n/4;
            M k;
            
//memset(k.m,0,sizeof(k.m));
            k=pow(c,num1);
            M q,qq;
            q
=Mult(k,k);
            qq
=Mult(q,q);
            rot
=Add(Add(Add(k,k),q),qq);
        }
        
if(n&1)
        {
            M cn;
            memset(cn.m,
0,sizeof(cn.m));
            cn.m[
0]=1;
            cn.m[
1]=4;
            
ref=Mult(cn,pow(c,(n+1)*n/2));
        }
        
else 
        {
            M an;
            an
=pow(c,(n+1)*n/2);
            M bn;
            bn
=pow(c,n*n/2);
            
ref=Add(Add(an,an),Add(bn,bn));
        }
        M Final;
        Final
=Div(Add(ref,rot),8);
        
for(i=Final.m[0];i>=1;i--)
            printf(
"%d",Final.m[i]);
        printf(
"\n");
    }
    
return 0;
}