您的位置:首页 > 其它

21位花朵数算法

2013-05-04 10:06 274 查看
/*
128468643043731391252
449177399146038697307*/
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<time.h>

/*
128468643043731391252
449177399146038697307*/
//我的程序只用了34秒
//乍一下很难,很容易往那个一位位枚举数字的方向去,但是这样的复杂度很高,尽管加上了一些判断还是于事无补
//我说一下思路吧,先把所有的数字的21次方求出来放在一个数组里保存,然后再去枚举每一个数字有几个,
//总共加起来是二十一位数字,这个枚举的操作次数相对刚才的那个是小多了,
//然后把这些数的21次方加起来,然后再去判断一下,是不是由这些数字组成就行了

const int BIT=100000000;
struct BigNum
{
int dig[6];
int len;
void Clr()
{
memset(dig,0,sizeof(dig));
len=1;
}
void Print()
{
int i;
printf("%d",dig[len-1]);
for(i=len-2;i>=0;i--)
printf("%08d",dig[i]);
puts("");
}
};
BigNum p[10],MAX,MIN;
BigNum sp[10][22];
int take[10]={0};
int LEN=21;
int GetLen(BigNum a)
{
int i;
for(i=5;i>0&&a.dig[i]==0;i--);
return i+1;
}
BigNum CarryUp(BigNum a)
{
int i;
for(i=0;i<a.len;i++)
{
a.dig[i+1]+=a.dig[i]/BIT;
a.dig[i]%=BIT;
}
return a;
}
BigNum Multi(BigNum a,BigNum b)
{
BigNum c;
int i,j,k;
c.Clr();
c.len=a.len+b.len;
for(i=0;i<a.len;i++)
{
for(j=0;j <b.len;j++)
{
c.dig[i+j]+=a.dig[i]*b.dig[j];
}
}
c=CarryUp(c);
if(c.len>0&&c.dig[c.len-1]==0)c.len--;
return c;
}
BigNum MyPow(BigNum a,int n)
{
BigNum ret;
ret.Clr();
ret.dig[0]++;
while(n--)
{
ret=Multi(ret,a);
}
return ret;
}
int Cmp(BigNum a,BigNum b)
{
if(a.len>b.len)return 1;
if(a.len<b.len)return -1;
int i;
for(i=a.len-1;i>=0&&a.dig[i]==b.dig[i];i--);
if(i==-1)return 0;
return a.dig[i]-b.dig[i];
}
BigNum Add(BigNum a,BigNum b)
{
int i;
if(b.len>a.len)a.len=b.len;
for(i=0;i<a.len;i++)
{
a.dig[i]+=b.dig[i];
}
a=CarryUp(a);
if(a.dig[a.len])a.len++;
return a;
}
BigNum Deal(BigNum a)
{
int i;
BigNum b;
b.Clr();
b.len=3;

for(i=7;i>=0;i--)
{
b.dig[0]=b.dig[0]*10+a.dig[i];
}
for(i=15;i>=8;i--)
{
b.dig[1]=b.dig[1]*10+a.dig[i];
}
for(i=23;i>=16;i--)
{
b.dig[2]=b.dig[2]*10+a.dig[i];
}
return b;
}
bool ok(BigNum sum)
{
int aa[10]={0};
int i;
for(i=0;i<8;i++)
{
aa[sum.dig[0]%10]++;
aa[sum.dig[1]%10]++;
sum.dig[0]/=10;
sum.dig[1]/=10;
}
for(i=0;i<5;i++)
{
aa[sum.dig[2]%10]++;
sum.dig[2]/=10;
}
for(i=0;i<10&&aa[i]==take[i];i++);
return i==10;
}
void DFS(int deep,BigNum Sum,int leave)
{
BigNum check;
BigNum cc;
int i;
if(deep==10)
{
if(leave>0)return;

if(ok(Sum))
{
Sum.Print();
}
return ;
}

for(i=0;i<=leave;i++)
{
take[deep]=i;
check=Add(Sum,sp[deep][i]);
if(Cmp(check,MAX)>=0)break;
cc=Add(check,sp[9][leave-i]);
if(Cmp(cc,MIN)<0)continue;
DFS(deep+1,check,leave-i);
}
}
int main()
{
int i;
int j;
BigNum tmp;
BigNum sum;
tmp.Clr();
int start=time(NULL),finish;

for(i=0;i<10;i++)
{
p[i]=MyPow(tmp,LEN);
tmp.dig[0]++;
}
for(i=0;i<10;i++)sp[i][0].Clr();
for(j=0;j<10;j++)
for(i=1;i<22;i++)
{
sp[j][i]=Add(sp[j][i-1],p[j]);
}
tmp.Clr();
tmp.len=LEN;

sum.Clr();
MAX.dig[2]=100000;
MAX.len=3;
MIN.dig[2]=10000;
MIN.len=3;
DFS(0,sum,LEN);
finish = time(NULL);
printf("%d\n",(finish-start));
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: