专栏文章

P13098 构造大师贝贝 题解

P13098题解参与者 3已保存评论 2

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
2 条
当前快照
1 份
快照标识符
@mioyzu8n
此快照首次捕获于
2025/12/03 03:27
3 个月前
此快照最后确认于
2025/12/03 03:27
3 个月前
查看原文

1. 题意解释

给出一个数 nn,每次你可以选择 nn 的一个因数 mm,并使 n=n+mn=n+mmm 不可重复,求如何使 nn 成为一个完全平方数。

2. 思路

主播赛时切掉了这道抽象的构造题来讲一下心路历程。
最开始时肯定会想到往最近的完全平方数靠。
然而这样我们会发现,有些数字是无法变成与其最接近的完全平方数的。
例子:77
77 最接近的完全平方数是 99,可你会发现没有办法使 77 转化为 99
主播本来这时候打算放弃了。
然而数竞的经历让主播想到了分类讨论整除性
我们考虑对 nn 分类讨论。
  • n1(mod4)n\equiv1\pmod4
我们让 nn 加上 11(这是显然可行的),此时 n+1n+1 是一个偶数(显然),再让其加上 22,此时变为 n+3n+3,变成一个 44 的倍数。
  • n2(mod4)n\equiv2\pmod4
直接让 nn 加上 22(显然可行)变为 n+2n+2,依然化为 44 的倍数。
  • n3(mod4)n\equiv3\pmod4
直接让 nn 加上 11(显然可行)变为 n+1n+1,依然化为 44 的倍数。
此时,对于所有 nn 都已化为 44 的倍数,我们让 nn 除以 44,转化为 n/4n/4
不难发现这样的操作可以一直持续直到 nn 已成为一个完全平方数。
至于操作次数,最坏的情况是 2log4n2\log_4n,若 100100 次操作用完可以达到 4504^{50},大约是 103110^{31}
而操作过程中 nn 的最大值显然为 4log4n+14^{\left\lfloor\log_4n\right\rfloor+1},不会超过 101810^{18},因而此方法可行。

3. 代码实现

没什么特别难的地方,直接上主播的 code:
CPP
#include<bits/stdc++.h>
#define int long long
using namespace std;
int t,n,cnt;
vector<int>vec;
void solve(int x,int a){
	if(floor(sqrt(x))*floor(sqrt(x))==x){
		cout<<cnt<<endl;
		for(int i=0;i<vec.size();i++){
			cout<<vec[i]<<" ";
		}
		cout<<endl;
	}
	else{
		if(x%4==1){
			cnt+=2;
			vec.push_back(a);
			vec.push_back(2*a);
			solve((x+3)/4,a*4);
		}
		else if(x%4==2){
			cnt++;
			vec.push_back(2*a);
			solve((x+2)/4,a*4);
		}
		else if(x%4==3){
			cnt++;
			vec.push_back(a);
			solve((x+1)/4,a*4);
		}
		else{
			solve(x/4,a*4);
		}
	}
}
signed main(){
	cin>>t;
	while(t--){
		cin>>n;
		cnt=0;
		vec.clear();
		solve(n,1);
	}
	return 0;
}

评论

2 条评论,欢迎与作者交流。

正在加载评论...