java大数详解

引论

在算法竞赛中我们经常遇到大数问题,例如求一个很大的斐波那契数。住在这种情况下我们用常规解法(使用long long或long long int)肯定是不行的,而我们自己写一个大数的算法又过于麻烦且易于出错,在这种情况下使用java中自带的大数类是我们最好的选择

介绍

java中用于操作大数的类主要有两个,一个是BigInteger,代表大整数类用于对大整数进行操作,另一个是BigDecimal,代表大浮点型。因为这两种类的使用方法是一样的且通常情况下我们处理的数据是整数,所以下面我们以BigInteger为例进行讲解

基本用法

1、新建一个值为123的大整数对象

BigInteger a=new BigInteger(“123”);  //第一种,参数是字符串
BigInteger a=BigInteger.valueOf(123);    //第二种,参数可以是int、long

2、大整数的四则运算

a. add(b);    //a,b均为BigInteger类型,加法
a.subtract(b);   //减 法
a.divide(b);  //除法
a.multiply(b);    //乘法

3、大整数比较大小

a.equals(b);  //如果a、b相等返回true否则返回false
a.compareTo(b);  //a小于b返回-1,等于返回0,大于返回1

4、常用方法

 a.mod(b);  //求余
 a.gcd(b);  //求最大公约数
 a.max(b);  //求最大值
 a.min(b);  //求最小值

5、BigInteger中的常数

BigInteger.ZERO    //大整数0
BigInteger.ONE    //大整数1
BigInteger.TEN   //大整数10

6、求大整数的位数

//先转换成字符串再求字符串的长度
a.toString().length();   //a的类型为BigInteger

输入框架

场景一

不断读入数据直至文件尾,或者说有多组测试用例以EOF为结束标志

    Scanner cin = new Scanner(System.in); //相当于C++中的cin,只不过这个cin需要自己创建
    while(cin.hasNext()){  //等同于!=EOF
        BigInteger a;
        a = cin.nextBigInteger();   //读入一个BigInteger;
        System.out.println(a);   //输出a并换行
    }

场景二

输入一个整数T,代表有T组测试样例

    Scanner cin = new Scanner(System.in);
    int T = cin.nextInt();
    while (T-- > 0) {
        System.out.println(T);
    }

注意

使用java大数类解决问题时我们需要注意两个方面
1、不能有包名,也就是说我们要把主类放到默认的包里,如果你的代码里出现形如package cn.gov.test;这样的代码你很有可能会收获到RE
2、提交的类的类名必须为Main,如果是其他的名字你有可能收获到CE也有可能收获到WA(例如UVA)
3、不要想当然的认为执行了a.add(b)之后a的值会发生改变,这句代码只是求值而已,相当于a + b,计算了a + b之后a的值会改变吗?当然不会!所以我们要想达到 a = a + b的效果需要写a = a.add(b)

例题

1、A == B ?
题目描述:输入两个非常大的数A和B,判断A是否等于B,如果相等输出YES,否则输出NO
分析:这个题在hdu上实际上并没有给出范围,WA了之后才知道这是道大数题,因为仅仅涉及到输入、比较和输出,所以非常适合用作大数的入门题
注意:这里只是说给出两个数A和B,并没有说是两个整数,所以应该采用BigDecimal
参考代码

import java.math.BigDecimal;
import java.util.Scanner;

public class Main {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		
		BigDecimal a, b;
		Scanner cin = new Scanner(System.in);
		
		while (cin.hasNext()) {
			a = cin.nextBigDecimal();
			b = cin.nextBigDecimal();
			if (a.compareTo(b) == 0) System.out.println("YES");
			else System.out.println("NO");
		}

	}

}

2、大整数加法
题目描述:求两个不超过200位的非负整数的和。
分析:也是非常简单的入门题,直接输入后调用BigInteger自带的方法add即可
参考代码

import java.math.BigInteger;
import java.util.Scanner;

public class Main {
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		
		BigInteger a,b;
		
		Scanner cin = new Scanner(System.in);
		
		a = cin.nextBigInteger();
		b = cin.nextBigInteger();
		
		System.out.println(a.add(b));
	}

}

3、大数阶乘
题目描述:给你一个n,计算n的阶乘,但是n很可能比较大
分析:因为m很小只有5000所以我们可以从1开始打一个阶乘表,这样的话当有输入的时候我们就可以用O(1)的复杂度解决它
参考代码

import java.math.BigInteger;
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        BigInteger f[] = new BigInteger[5500];
        f[0] = f[1] = BigInteger.ONE;
        for (int i = 2; i <= 5000; ++i) {
            f[i] = f[i - 1].multiply(BigInteger.valueOf(i));
        }
        Scanner cin = new Scanner(System.in);
        while (cin.hasNext()) {
            int m = cin.nextInt();
            System.out.println(f[m]);
        }
    }
}

4、大菲波数
题目描述:计算第n项Fibonacci数值,n可能比较大
分析:这个题与上一题一样,需要先打表在输出
参考代码

import java.math.BigInteger;
import java.util.Scanner;


public class Main {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner cin = new Scanner(System.in);
		
		BigInteger[] nums = new BigInteger[1010];
		nums[1] = new BigInteger("1");
		nums[2] = new BigInteger("1");
		for(int i = 3; i <= 1000; i++)
			nums[i] = nums[i - 1].add(nums[i - 2]);
		
		int T = cin.nextInt();
		while(T > 0)
		{
			T--;
			int n = cin.nextInt();
			System.out.println(nums[n]);
		}

	}

}

5、A/B
题目描述:要求(A/B)%9973,但由于A很大,我们只给出n(n=A%9973)(我们给定的A必能被B整除,且gcd(B,9973) = 1)。
分析:最容易想到的方法莫过于让n一直加9973加到n Mod b == 0,不过很可惜这样做会超时的;所以我们换一种思路,因为a一定能被b整除,所以a一定是b的倍数,于是我们让a = b * i(i= 1,2,3···)直到a Mod b == n;此时得到大整数a直接用题目中给的公式就能将正确答案做出来

参考代码

import java.math.BigInteger;
import java.util.Scanner;

public class Main {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		
		Scanner cin = new Scanner(System.in);
		int T = cin.nextInt();
		while(T > 0)
		{
			T--;
			BigInteger a = cin.nextBigInteger();
			BigInteger b = cin.nextBigInteger();
			BigInteger d = new BigInteger("9973");
			BigInteger z = new BigInteger("0");
			
			
			for(BigInteger i = new BigInteger("1"); ; i = i.add(new BigInteger("1")))
			{
				BigInteger c = b.multiply(i);
				if(c.mod(d).compareTo(a) == 0)
				{
					System.out.println(i.mod(d));
					break;
				}
			}
		}

	}

}

你可能感兴趣的:(算法,ACM常用算法)