ACM-ICPC 2017 Asia HongKong - A (JAVA大数)

Consider the error function F(x,y,z,n)=∣xn+yn−zn∣F(x,y,z,n)=xn+ynzn, where ∣v∣v means the absolute value of vv. Given two positive integers nn and zz, our problem is to find two positive integers xx and yy such that x<y<zx<y<z and the error value F(x,y,z,n)F(x,y,z,n) is minimized.

For example, if we are given n=3n=3 and z=9z=9, then the solution is: x=6x=6 and y=8y=8. This solution yields the error value 11.

Input

The first line contains the number of test cases T(T<10)T(T<10). Each subsequent line corresponds to a test case, which contains two positive integers n(2<n<10)n(2<n<10) and z(1<z<100000)z(1<z<100000).

Output

For each test case, output the value of xxyy, and F(x,y,z,n)F(x,y,z,n) in a line, separated by spaces.

样例输入
2
3 9
3 7
样例输出
6 8 1
5 6 2
题目来源

ACM-ICPC 2017 Asia HongKong

找出F最小。


POINT:

大树+二分模拟。思路还是挺简单的。就是java写起来麻烦。另外可以打表的,比如一些重复用到的大树进行幂运算,打表处理。不然TLE。


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


public class Main {
	static BigInteger one = BigInteger.ONE;
	static BigInteger zero = BigInteger.ZERO;
	private static Scanner cin;
	static BigInteger z;
	static int n;
	public static BigInteger qkm(int n,BigInteger base) {
		BigInteger ans = one;
		for(int i=1;i<=n;i++) {//这根本就不是快速幂!!
			ans=ans.multiply(base);
		}
		return ans;
		
	}
	static BigInteger ans;
	public static int check(int x,int y) {
		BigInteger xx = BigInteger.valueOf(x);
		BigInteger yy = BigInteger.valueOf(y);
		ans = qkm(n, xx).add(qkm(n, yy)).subtract(qkm(n, z));
		return ans.compareTo(zero);
		
	}
	
	public static void main(String args[]) {
		cin = new Scanner(System.in);    
		 int T=cin.nextInt();
		 while(T--!=0) {
			 n=cin.nextInt();
			 z=cin.nextBigInteger();
			 int ansx = 0,ansy=0;
			 BigInteger aim=BigInteger.valueOf(1);
			 for(int p=1;p<=100;p++) aim=aim.multiply(BigInteger.valueOf(10));
			 BigInteger inf = aim;
			 int num=0;
			 int l=1,rr=z.intValue()-1;
			 for(int i=rr;i>=1;i--) {
				 if(num>5000) break;
				 num++;
				 BigInteger fu=inf.multiply(BigInteger.valueOf(-1));
				 BigInteger zheng = inf;
				 l=1;
				 int r=i-1;
				 int fy=0,zy=0;
				 while(l<=r) {
					int mid = (l+r)>>1;
				 	if(check(i,mid)==-1) {
				 		if(fu.compareTo(ans)==-1) {
				 			fu=ans;
				 			fy=mid;
				 		}
				 		l=mid+1;
				 	}else if(check(i, mid)==0) {
				 		zy=mid;
				 		aim=zero;
				 		break;
				 	}else {
				 		if(zheng.compareTo(ans)==1) {
				 			zheng=ans;
				 			zy=mid;
				 		}
				 		r=mid-1;
				 	}
				 }
				 if(aim.compareTo(zero)==0) {
					 ansx=i;
					 ansy=zy;
					 break;
				 }
				 fu=fu.multiply(BigInteger.valueOf(-1));
				 if(aim.compareTo(fu)==1) {
					 aim=fu;
					 ansx=i;
					 ansy=fy;
					 num=0;
				 }
				 if(aim.compareTo(zheng)==1) {
					 aim=zheng;
					 ansx=i;
					 ansy=zy;
					 num=0;
				 }
			 }
			 if(ansx>ansy) {
				 int t=ansx;
				 ansx=ansy;
				 ansy=t;
			 }
			 System.out.println(ansx+" "+ansy+" "+aim);
		 }
		
		
	}
}





第二个:

这个应该才是正确的。上面那个是把数据卡过了。


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


public class Main {
	static BigInteger one = BigInteger.ONE;
	static BigInteger zero = BigInteger.ZERO;
	static BigInteger haha;
	static BigInteger z;
	static int n;
	public static BigInteger qkm(int n,BigInteger base) {
		BigInteger ans = one;
		while(n!=0) {
			if(n%2==1)
				ans=ans.multiply(base);
			base=base.multiply(base);
			n>>=1;
		}
		return ans;
	}
	static BigInteger ans;
	static BigInteger xxx;
	public static int check(int x,int y) {
		BigInteger yy = BigInteger.valueOf(y);
		ans = xxx.add(qkm(n, yy)).subtract(haha);
		return ans.compareTo(zero);
		
	}
	
	public static void main(String args[]) {
		Scanner cin = new Scanner(System.in);    
		 int T=cin.nextInt();
		 while(T--!=0) {
			 n=cin.nextInt();
			 z=cin.nextBigInteger();
			 int ansx = 0,ansy=0;
			 BigInteger aim=BigInteger.valueOf(1);
			 for(int p=1;p<=100;p++) aim=aim.multiply(BigInteger.valueOf(10));
			 BigInteger inf =  aim;
			 haha=qkm(n, z);
			 int l=1,rr=z.intValue()-1;
			 for(int i=rr;i>=1;i--) {
				 xxx=qkm(n,BigInteger.valueOf(i));
				 BigInteger fu=inf.multiply(BigInteger.valueOf(-1));
				 BigInteger zheng = inf;
				 l=1;
				 int r=i-1;
				 int fy=0,zy=0;
				 while(l<=r) {
					int mid = (l+r)>>1;
				 	if(check(i,mid)==-1) {
				 		if(fu.compareTo(ans)==-1) {
				 			fu=ans;
				 			fy=mid;
				 		}
				 		l=mid+1;
				 	}else if(check(i, mid)==0) {
				 		zy=mid;
				 		aim=zero;
				 		break;
				 	}else {
				 		if(zheng.compareTo(ans)==1) {
				 			zheng=ans;
				 			zy=mid;
				 		}
				 		r=mid-1;
				 	}
				 }
				 if(aim.compareTo(zero)==0) {
					 ansx=i;
					 ansy=zy;
					 aim=zero;
					 break;
				 }
				 fu=fu.multiply(BigInteger.valueOf(-1));
				 if(aim.compareTo(fu)==1) {
					 aim=fu;
					 ansx=i;
					 ansy=fy;
				 }
				 if(aim.compareTo(zheng)==1) {
					 aim=zheng;
					 ansx=i;
					 ansy=zy;
				 }
			 }
			 if(ansx>ansy) {
				 int t=ansx;
				 ansx=ansy;
				 ansy=t;
			 }
			 System.out.println(ansx+" "+ansy+" "+aim);
		 }
		
		
	}
}



  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值