我的欧拉工程之路——29

题目29:a的b次方(2≤a,b≤100)中共有多少个不同的数?

考虑 ab 在 2  a  5,2  b  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  a  100,2  b  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<l;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<ArrayLen;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<ArrayLen;i++)
		{
			num[i]=a.num[i];
		}
	}
	public void add(Num b)
	{
		for(int i=0,jinwei=0;i<ArrayLen;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<len/4;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<p;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<pos;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;
            }
        }
    }
}

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

我的欧拉工程之路——29,布布扣,bubuko.com

时间: 2024-10-18 02:02:56

我的欧拉工程之路——29的相关文章

Java进阶之欧拉工程 第十五篇【网格路径问题】

网格路径问题,中文翻译如下: 从 22的格子的左上角开始,只允许向右和向下移动,一共有六种路径可以抵达右下角 那么在2020的路径中一共有多少条这样的路径? 原题如下: Starting in the top left corner of a 22 grid, and only being able to move to the right and down, there are exactly 6 routes to the bottom right corner. How many such

Java进阶之欧拉工程 第十五篇【2的1000次方各位之和为多少】

题目如下: 215 = 32768 并且其各位之和为 is 3 + 2 + 7 + 6 + 8 = 26. 21000 的各位数之和是多少? 原题如下: 215 = 32768 and the sum of its digits is 3 + 2 + 7 + 6 + 8 = 26. What is the sum of the digits of the number 21000? 解题思路:这道题和之前的大数求和的思想有点类似,就是用数组存储大数的每一位数,然后相加,上次写的大数相加的函数稍作

欧拉工程第70题:Totient permutation

题目链接 和上面几题差不多的 Euler's Totient function, φ(n) [sometimes called the phi function]:小于等于n的数并且和n是互质的数的个数 存在这样的数:N的欧拉数φ(n),是N的一个排列 例如:φ(87109)=79180 求在1---10^7中n/φ(n) 取到最小的 n 是多少? 这里的是p是n的素因子,当素因子有相同的时候只取一个 任意一个正整数都能分解成若干个素数乘积的形式 直接利用上题的phi函数就可以求解 这个是跑的最

欧拉计划(python) problem 29

Distinct powers Problem 29 Consider all integer combinations of ab for 2 ≤ a ≤ 5 and 2 ≤ b ≤ 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 If they are then placed in numerical orde

欧拉工程第71题:Ordered fractions

题目链接:https://projecteuler.net/problem=71 If n<d and HCF(n,d)=1, it is called a reduced proper fraction. n/d 真分数升序排序后,离 3/7最近的数,d<=1000000 Java程序: public class P71{ void run(){ calculate(); } void calculate(){ int max_n = 1000000; long a = 3; long b

欧拉工程第73题:Counting fractions in a range

题目链接:https://projecteuler.net/problem=73 n/d的真分数 ,当d<=12000时 在 1/3 and 1/2 之间的有多少个 public class P73{ void run(){ FareySequences(); } void FareySequences(){ int limit = 12000; int a = 1; int b = 3; int c = 4000; int d = 11999; int count=0; while(!(c==

欧拉工程第51题:Prime digit replacements

题目链接 题目: 通过置换*3的第一位得到的9个数中,有六个是质数:13,23,43,53,73和83. 通过用同样的数字置换56**3的第三位和第四位,这个五位数是第一个能够得到七个质数的数字,得到的质数是:56003, 56113, 56333, 56443, 56663, 56773, 和 56993.因此其中最小的56003就是具有这个性质的最小的质数. 找出最小的质数,通过用同样的数字置换其中的一部分(不一定是相邻的部分),能够得到八个质数. 解题思想: 这个题目是很难的 你首先要找到

欧拉工程第52题:Permuted multiples

题目链接 题目: 125874和它的二倍,251748, 包含着同样的数字,只是顺序不同. 找出最小的正整数x,使得 2x, 3x, 4x, 5x, 和6x都包含同样的数字. 这个题目相对比较简单 暴力遍历 判断x,2x,3x,4x,5x,6x是否包含的数字相同 如何判断两个数包含的数字相同? 1. 两个数字转换成字符串后:d1,d2 定义两个集合ts1,ts2, 将d1,d2的各位数都添加到集合ts1中 将d1的各位数添加到集合ts2中 最后这个两个集合相等,则,这个两个数包含相同的数字 2.

欧拉工程第67题:Maximum path sum II

By starting at the top of the triangle below and moving to adjacent numbers on the row below, the maximum total from top to bottom is 23. 37 42 4 68 5 9 3 That is, 3 + 7 + 4 + 9 = 23. Find the maximum total from top to bottom in triangle.txt (right c