四平方和(第七届蓝桥杯省赛C++A/B组)

样例输入:

5

样例输出:

0 0 1 2

分析:首先看数据范围我们可以发现a,b,c,d都是小于2500的,那么我们如果要是枚举的话最多只能枚举两个数,一种简单的思路是我们枚举前三个数,然后直接可以计算出第四个数是否存在,但看到数据范围后我们就可以发现这种方法是行不通的,那么接下来我们就需要想一种方法来简化。

想法就是使得在a和b足够小的前提下让c也尽可能地小,a和b足够小的前提应该怎么保证呢?这个很简单,我们可以直接暴力枚举,那么这也就意味着接下来我们要在O(1)的复杂度内找到满足n-a*a-b*b=c*c+d*d的最小c,容易发现我们可以预处理一个数组来实现这个功能,含义如下:

f[x]存储满足i*i+j*j=x的最小的i

其中初始化f数组为-1,那么当f[x]=-1时代表这样的数对是不存在的

那么在枚举a和b的前提下,我们只需要O(1)访问f[n-a*a-b*b]便可以知道是否存在满足n-a*a-b*b=c*c+d*d的数对(c,d),如果存在则可以直接找到c,所以整体的复杂度就可以满足题意了。

细节见代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<map>
#include<queue>
#include<vector>
#include<cmath>
using namespace std;
const int N=5e6+10;
int f[N];//f[x]存的是满足i*i+j*j=x的最小的i
int main()
{
	memset(f,-1,sizeof f);
	//f[x]=-1代表不存在数对(i,j)满足i*i+j*j=x
	int n;
	scanf("%d",&n);
	for(int i=0;i*i*2<=n;i++)
	for(int j=i;i*i+j*j<=n;j++)
		if(f[i*i+j*j]==-1)
			f[i*i+j*j]=i;
	for(int i=0;i*i*4<=n;i++)
	for(int j=0;i*i+j*j<=n/2;j++)
	{
		int t=n-i*i-j*j;
		if(f[t]!=-1)
		{
			printf("%d %d %d %d",i,j,f[t],(int)sqrt(t-f[t]*f[t]));
			return 0;
		}
	}
	return 0;
} 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值