• [HDU4143] A Simple Problem


    题目

    原题地址

    解说

    显然数学题。
    因为(y^2=n+x^2),所以移一下项可以得到(y^2-x^2=n),即((y+x)(y-x)=n),这样就很显然了,我们把(n)分解为(a,b),只要满足(a=y+x,b=y-x),即(a+b=2y,a-b=2x),即(a-b)是偶数即可,(x)就等于((a-b)/2)
    如果我们直接从(1)开始分解质因数的话,显然时间效率是(O(sqrt n)),这个效率似乎不能再优化了,但是用一个小技巧可以让它稍微快一些。我们要找的是最小的(x),即我们想让(a,b)最接近,那么我们就不应该改从(1)开始循环,而应该从(sqrt n)开始,这样我们找到的第一组符合条件的(a,b)就一定是差最小的,这时候直接(break)就行了,没必要再继续下面的循环了。
    另外注意一点,题目中说了(positive integer x),即(x)是个正数,那么(n)是完全平方数的话输出(0)就错了(这个点卡了我一节课)

    代码

    #include<bits/stdc++.h>
    using namespace std;
    int main(){
    	int t;
    	scanf("%d",&t);
    	while(t--){
    		int n;bool flag=0;
    		scanf("%d",&n);
    		for(int i=sqrt(n);i>=1;i--){
    			if(n%i==0){
    				int b=n/i;
    				if(b==i) continue;
    				if((b-i)%2==0){
    					printf("%d
    ",(b-i)/2);
    					flag=1;
    					break;
    				}
    			}
    		}
    		if(!flag) printf("-1
    ");
    	}
    	return 0;
    }
    

    尾声:关于gyz大佬代码冗余部分的评论

    最开始确实没发现(x)是正数这么回事,于是找来了(gyz)大佬的代码对拍,才发现了这个错,但是反观他的代码有许多冗余部分,很不优美,也不简洁,极大地影响了阅读体验,下面进行简短评论。

    #include<cstdio>
    int main(){
    	int T;
    	scanf("%d",&T);
    	while(T--){
    		int n,res=-1;
    		scanf("%d",&n);
    		for(int i=1;i*i<n;i++){//没有从根号n开始影响时间,但这是思路的问题,无可厚非
    			if(n%i)continue;
    			int a=n/i;
    			if((a+i)%2||(a-i)%2||a-i<0)continue;//首先(a+i)%2,(a-i)%2只判一个就行,因为a-i是偶数a+i一定是偶数
                            //(a-i)<0用不着判断,a一定是大于i的,毕竟i是小于根号n的
    			if(res==-1||res>(a-i>>1))res=a-i>>1;//这里不用判断,毕竟以1到根号n的顺序找的话x一定是越来越小的
    		}
    		printf("%d
    ",res);
    	}
    	return 0;
    }
    

    (以上仅是个人意见,无意侵犯)
    幸甚至哉,歌以咏志。

  • 相关阅读:
    bootstrap 学习笔记
    js 学习笔记 -- webpack 简介
    js 学习笔记 -- webapi
    js 学习笔记 -- js基础知识
    css学习笔记二--IFC
    css 学习笔记一
    vim学习笔记
    Linux 网络命令
    Java中循环冗余校验(CRC32)的实现
    Tomcat8启动报there was insufficient free space available after evicting expired cache entries
  • 原文地址:https://www.cnblogs.com/DarthVictor/p/12951450.html
Copyright © 2020-2023  润新知