# [题解] 2023 杭电多校 Rikka with Square Numbers [数论]

哎,数学!

# 题目大意

每次操作可以加或者减一个完全平方数,问至少多少次可以把aa 变成bb
1a,b1091 \le a,b\le 10^9

# 题解

看到这个题面首先想了dpdp 或者搜索的做法。
发现这里的加减两个方向的转移其实没办法很好地dpdp。而且并没有找到合理的操作策略,不像是直接能递推出来的。
所以大概率是个结论题。然而我对数学不那么敏感,也推不出来什么式子。
如果当初先暴力打个表说不定就有思路了,那就能看到答案其实只有112233
那么我们就分类讨论。为了方便这里不妨令a>ba\gt b,反正操作可逆,做等价交换。

  • 答案是11 的情况:即aba-b 是一个完全平方数。
  • 答案是22 的情况:aba-b 不是完全平方数,但是可以由两个完全平方数或加或减凑出来。令d=abd=a-b
    • 如果是两个平方数相加得到dd,令d=x2+y2d=x^2+y^2,这时候通过枚举即可在O(d)\mathcal{O}(\sqrt d) 时间内判断。
    • 如果是两个平方数相减得到dd,令d=x2y2d=x^2-y^2,不妨令x>yx\gt y。我们有平方差公式d=x2y2=(x+y)(xy)d=x^2-y^2=(x+y)(x-y)。这时再对xxyy 的奇偶性做一下讨论:
      • xxyy 一奇一偶,那么(x+y)(xy)(x+y)(x-y) 显然是奇数。一个奇数dd 必然可以找到xxyy 满足d=x+yd=x+yxy=1x-y=1。也就是说 d 为奇数的情况自然满足操作两步可达。
      • xxyy 双奇或双偶,那么(x+y)(xy)(x+y)(x-y) 显然是44 的倍数。令d=4kd=4k,这时令x=k+1,y=k1x=k+1,y=k-1 即可满足。
  • 答案不为1122 时,注意到这时dd 一定为偶数 (dd 为奇数一定至少22 步可以完成), 那么我们只要先用11 步将dd 减掉11, 即可再用22 步满足,所以答案为33
    至此,所有情况讨论完了。代码主要只有一个判断两平方之和的循环,时间复杂度O(a+b)\mathcal{O}(\sqrt{a+b})

# 代码

#include<cstdio>
#include<map>
#include<cmath>
const int MAXN=1e9;
bool isqr(const int &x){
	if(x==0) return 0;
	int t=sqrt(x);
	return t*t==x;
}
int main(){
	int T;
	scanf("%d",&T);
	while(T--){
		int a,b;
		scanf("%d%d",&a,&b);
		int d=a-b;
		if(d<0) d=-d;
		if(d==0)
			printf("0\n");
		else if(isqr(d))
			printf("1\n");
		else if(d&1 || d%4==0)
			printf("2\n");
		else{
			bool fg=0;
			for(int i=1;i*i<d && !fg;++i)
				if(isqr(d-i*i))
					fg=1;
			if(fg)
				printf("2\n");
			else
				printf("3\n");
		}
	}
}
更新于 阅读次数