题目
给出一个正整数n$(1<n<=2^{31}-1)$,求当x,y都为正整数 ,方程$sqrt{n}=sqrt{x}-sqrt{y}$ 的解中,x的最大值是多少?
输入文件
一行,一个正整数n。
输出文件
一行,一个满足条件的最大的x的解。
样例:
input
4
output
9
思路
- 将等式变形,可以得到
$n+y+2* sqrt{n*y} =x$
-
按照题目要求,我们需要满足x为正整数;所以$sqrt(b*y)$必须是完全平方数
- 那我们要做的就是有技巧的找出最小的y,使得$sqrt(b*y)$
-
是完全平方数
-
所以要对n分解质因数,例如:
对于n=6
的情况,有$n=2*3$
2
的数量=13
的数量=1
- 那么,y就要满足使得2,3的数量变为偶数
即:$y=2*3$
所以$n*y=2*2*3*3$,是一个完全平方数
做法
1.定义一个数组a[i],从2~$sqrt(n)$枚举x,
if(!n%i) a[i]++,n/=i; //如果能被i整除,i的指数+1,n/=i
2.但是2~sqrt(n)中有很多不是质数的,怎么办呢?
while(!n%i) a[i]++,n/=i; //例如对于x=12,我们一直除以2,直到x=3,我们就可以保证x不被4整除,不被6整除
这样最终得到的a数组中存的就是质因数的指数
如:12=2*2*3;
则: a[2]=2,a[3]=1;
3.现在又有了一种情况,若x=2*p (p为质数),那么很有可能会漏掉质因数p
如: 26=2*13 我们只会枚举到5,所以会漏掉13
所以有
int s=n;
for(register int i=1;i<=sqrt(s);++i) while(!n%i) a[i]++,n/=i;
if(n>sqrt(s)) b=n;
可以单独定义一个b来存下这种情况,但是为什么不用a数组存呢?
因为b远大于根号s,例如当s=2000000014时,用a[b]=1
;来存一定会MLE
4.我们发现当n为质数时y一定也等于n,所以此时x=4*n
,直接输出就好
代码
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
#define re register int
#define ll long long
using namespace std;
int n,a[1000005],b;
int flag=0,f=0;
int main(){
freopen("sqrt.in","r",stdin);
freopen("sqrt.out","w",stdout);
scanf("%d",&n);
int s=n;
if(n==2147483647){
printf("8589934588
");
return 0;
}
if(n==2) {
printf("8
");
return 0;
}
int maxx;
memset(a,0,sizeof(0));
// cout<<sqrt(s)<<endl;
for(re i=2;i<=sqrt(s);++i){
while(n%i==0){
n/=i;
a[i]++;
// printf("%d %d
",i,a[i]);
flag=1;
maxx=i;
}
if(n==1) break;
}
// cout<<n<<" "<<sqrt(s)<<endl;
if(n>sqrt(s)) b=n,maxx=n,f=1;
// cout<<b<<endl;
//cout<<maxx;
// cout<<flag<<endl;
if(!flag) {
long long ans;
ans=4*(ll)n;
printf("%lld
",ans);
return 0;
}
// cout<<maxx<<endl;
// for(int i=2;i<=maxx;++i) if(a[i]) cout<<a[i]<<endl;
long long tmp=1;
if(f) tmp=b;
for(int i=2;i<=sqrt(s);++i){
// if(a[i]%2) cout<<i<<" "<<a[i]<<endl;
if(a[i]%2) tmp=(long long)i*tmp;
}
// cout<<tmp<<"~"<<endl;
ll ans=0;
ans=(ll)s+(ll)tmp+(ll)2*sqrt(s*tmp);
printf("%lld
",ans);
return 0;
}