java 欧拉工程_我的欧拉工程之路——29

考虑 ab 在 2

symbol_le.gif a 

symbol_le.gif 5,2 

symbol_le.gif b 

symbol_le.gif 5下的所有整数组合:22=4, 23=8, 24=16, 25=32

32=9, 33=27, 34=81, 35=243

42=16, 43=64, 44=256, 45=1024

52=25, 53=125, 54=625, 55=3125

如果将这些数字排序,并去除重复的,我们得到如下15个数字的序列:

4, 8, 9, 16, 25, 27, 32, 64, 81, 125, 243, 256, 625, 1024, 3125

ab 在 2

symbol_le.gif a 

symbol_le.gif 100,2 

symbol_le.gif b 

symbol_le.gif 100 下生成的序列中有多少个不同的项?

解答:欧拉工程有几道涉及大数运算的问题,例如,求2^1000,常常需要计算几百位的整数的加法,乘法等。于是,我自己实现了一个Num类,专门用来计算这种大数,可以满足欧拉工程的大数运算需求。

以下列出这个Num类的相关函数,并附上源码。此类目前可以完成2000位以下的加法、乘法、次方运算。如果需要增加支持的运算数范围,可以修改Num类中的arrayLen的值,其值乘以4便是支持的最大长度。//空构造函数,初始化数值为0

public Num()

//以整数初始化变量

public Num(int input)

//以字符串初始化

public Num(String str)

//清空变量,重置为0

public void clear()

//乘法,与b相乘,结果存储在调用者内

public void multiply(Num b)

//打印此变量

public void print()

//返回存储整数的长度

public int len()

//复制a

public void clone(Num a)

//加法,结果存储在调用者内

public void add(Num b)

//设置数,以整数设置

public void setNum(int input)

//设置数,用字符串设置

public void setNum(String str)

//计算a^p,结果存储于a中

public void pow(int p)

//返回所存储数的字符串

public String toString()

class Num

{

public static int ArrayLen = 500;

private int[] num = new int[ArrayLen];

public void multiply(Num b)

{

int jinwei=0,l=(b.len()+3)/4;

Num result=new Num(),temp=new Num();

for(int i=0;i

{

temp.clear();

for(int j=0;j<=(this.len()+3)/4;j++)

{

int t=(this.num[j]*b.num[i]+jinwei)%10000;

jinwei=(this.num[j]*b.num[i]+jinwei)/10000;

temp.num[i+j]=t;

}

result.add(temp);

}

this.clone(result);

}

public void clear()

{

for(int i=0;i

{

this.num[i]=0;

}

}

//打印变量

public int compare(Num b)

{

int result=0;

for(int i=ArrayLen-1;i>=0;i--)

{

if(this.num[i]!=b.num[i])

{

result=this.num[i]-b.num[i];

break;

}

else if(i==0)

{

result=0;

}

}

return result;

}

public void print()

{

int i=ArrayLen-1;

while(num[i]==0 && i>0)

i--;

System.out.print("num="+num[i]);

while(--i>=0)

{

if(num[i]<10)

{

System.out.print("000");

System.out.print(num[i]);

}

else if(num[i]<100)

{

System.out.print("00");

System.out.print(num[i]);

}

else if(num[i]<1000)

{

System.out.print("0");

System.out.print(num[i]);

}

else

{

System.out.print(num[i]);

}

}

System.out.println(" ");

}

//返回此num对象存储的整数的长度

public int len()

{

int len=0;

for(int i=499;i>=0;i--)

{

if(num[i]!=0)

{

if(num[i]<10)

len=i*4+1;

else if(num[i]<100)

len=i*4+2;

else if(num[i]<1000)

len=i*4+3;

else

len=i*4+4;

break;

}

else if(i==0)

{

len=1;

}

}

return len;

}

public void clone(Num a)

{

for(int i=0;i

{

num[i]=a.num[i];

}

}

public void add(Num b)

{

for(int i=0,jinwei=0;i

{

int t=(this.num[i]+b.num[i]+jinwei)%10000;

jinwei=(this.num[i]+b.num[i]+jinwei)/10000;

this.num[i]=t;

}

}

public Num(){}

public Num(int input)

{

this.setNum(input);

}

public Num(String str)

{

this.setNum(str);

}

public void setNum(int input)

{

int i=0;

this.clear();

while(input>0)

{

this.num[i]=input%10000;

input/=10000;

i++;

}

}

public void setNum(String str)

{

this.clear();

if(str.length()%4!=0)

{

int i=4-str.length()%4;

while(i-->0)

{

str="0".concat(str);

}

}

int len=str.length();

for(int i=0;i

{

this.num[i]=Integer.parseInt(str.substring(len-i*4-4,len-i*4));

}

}

//运算a^p,存储在a中

public void pow(int p)

{

if(p==0)

{

this.clear();

this.num[0]=1;

}

else if(p>0)

{

Num t=new Num();

t.clone(this);

for(int i=1;i

{

this.multiply(t);

}

}

}

public String toString()

{

String s=new String("num=");

int i=ArrayLen-1;

while(num[i]==0 && i>0)

i--;

s+=num[i];

while(--i>=0)

{

if(num[i]<10)

{

s+="000";

s+=num[i];

}

else if(num[i]<100)

{

s.concat("00");

s+=num[i];

}

else if(num[i]<1000)

{

s.concat("0");

s+=num[i];

}

else

{

s+=num[i];

}

}

return s;

}

}

实现这个类后非常简单就可以解决这个问题了,首先计算所有的数值,并将已计算的数值保存下来,以后获得的每个数值都跟之前的所有数进行比较,如果有重复的则不保存,反之,保存。以下是这部分的java代码。public class Euler29

{

public static void main(String[] args)

{

Num[] total=new Num[9801];

for(int i=0;i<9801;i++)

{

total[i]=new Num();

}

Num t=new Num(2),comp=new Num();

for(int i=2,pos=0;i<=100;i++)

{

for(int j=2;j<=100;j++)

{

t.setNum(i);

t.pow(j);

int k=0;

for(;k

{

if(t.compare(total[k])==0)

{

break;

}

}

if(k==pos)

{

total[pos++].clone(t);

}

}

}

for(int i=0;i<9801;i++)

{

if(total[i].compare(comp)!=0)

{

System.out.print(i+1+" ");

total[i].print();

}

else

{

break;

}

}

}

}

对于这道题,肯定有更简便的方法,但是我在做这道题的时候更加倾向于实现一个通用的大数运算的类,虽然这个类现在还不是很完善,比如,对于负数还不支持,另外,还未实现减法和除法,不过我会慢慢的加上这部分的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值