UVALive - 8355- Fermat‘s Optimization Problem

    科技2022-07-12  134

    题目: 自己的错误做法: 看到这个题目就想起来确定二维点坐标的类型,三分套三分,搞起,然后边界各种不对···试了一下忘了的其他整数三分板子,太菜了,边界全都有问题··陷入自闭。debug半小时不知道哪里有问题,最后发现整数三分有毒。 eg:

    while(r-l>1){ int m1=(l+r)/2,m2=(m1+r)/2; if(judge(m1)>judge(m2))//本题取绝对值最小值,故为凹函数 judge返回值为计算式绝对值 l=m1; else r=m2; }

    对于数据:n=3,z=11; 正解应该是: x=7,y=10; 差绝对值12 若l=6,r=10;  m1=8,m2=10; 得到l=8,r=10;   m1=9,m2=9; 好了,现在就是生死攸关的时刻,按照我现在的写法,接下来就是l=9; 再也回不到正确答案; 如果我改成 if(judge(m1)>=judge(m2)) 那对于原本能正确的 n=3,z=17; 又会出现同样的错误,导致结果偏离正解。

    仔细想想就是因为当r-l=2的时候,m1=l+1,又因为m2=(l+1+r)/2,喜闻乐见的,三分中很可能出现m1=m2的情况,然而这个m1的值可能在极限的左侧,也可能在极限的右侧,因此, 怎么写都是错的。 三分套三分在这里是行不通的。也可能我太菜了,找到的网上模板也都是错的。

    正解:   注意到z的范围只有1e5,且x<y<z;那,我们大可从1到z-2,枚举x,然后二分枚举y,最后保留最小值即可。枚举y的关键点在于y的极限值必然在 x n + y n − z n < = 0 {x}^{n}+{y}^{n}-z^{n}<=0 xn+ynzn<=0的最大y和 x n + y n − z n > 0 x^{n}+y^{n}-z^{n}>0 xn+ynzn>0的最小y之间。两者选其一即可。 唯一的坑点就是大数了,java捞我。

    import java.math.BigInteger; import java.util.Scanner; public class Main{ public static void main(String [] args) { Scanner read=new Scanner(System.in); int T; T=read.nextInt(); BigInteger [][]base=new BigInteger[100002][11]; for(int i=1;i<=100000;i++) { BigInteger temp=BigInteger.valueOf(i); base[i][1]=temp; for(int j=2;j<=10;j++) base[i][j]=base[i][j-1].multiply(temp); }//预处理所有数字的次幂 //System.out.println(base[2][1]+" "+base[2][10]); while((T--)>0) { int k=read.nextInt(),z=read.nextInt(); int xx = 0,yy=0; BigInteger res=base[z][k]; BigInteger limit=res; //System.out.println("z^k is "+res); for(int x=1;x<z-1;x++) { //System.out.print("x is "+x); int l=x+1,r=z-1,y=l; while(l<=r) { int mid=(l+r)>>1; if(base[x][k].add(base[mid][k]).subtract(limit).compareTo(BigInteger.ZERO)>=0) { r=mid-1; } else { y=mid; l=mid+1; } } //System.out.println(" y is "+y); BigInteger minus1=BigInteger.valueOf(-1); //System.out.println(" value of -1 is "+minus1); BigInteger value1=base[x][k].add(base[y][k]).subtract(limit); //System.out.println(" value1 is "+value1); if(value1.compareTo(BigInteger.ZERO)>=0) { if(res.compareTo(value1)>0) { res=value1; xx=x; yy=y; } } else { value1=value1.multiply(minus1); //System.out.println(" value1 is "+value1); if(y+1<z) { BigInteger value2=base[x][k].add(base[y+1][k]).subtract(limit); //System.out.println(" value2 is "+value2); if(value1.compareTo(value2)<=0) { if(res.compareTo(value1)>0) { res=value1; xx=x; yy=y; } } else { if(res.compareTo(value2)>0) { res=value2; xx=x; yy=y+1; } } } else { if(res.compareTo(value1)>0) { res=value1; xx=x; yy=y; } } } } System.out.println(xx+" "+yy+" "+res); } read.close(); } }
    Processed: 0.010, SQL: 8