一个等差数列是一个能表示成a, a+b, a+2b,…, a+nb (n=0,1,2,3,…) 在这个问题中a是一个非负的整数,b是正整数。
写一个程序来找出在双平方数集合S中长度为n的等差数列。双平方数集合是所有能表示成p2+q2的数的集合。
输入:第一行: N(3<= N<=25),要找的等差数列的长度。 第二行: M(1<= M<=250),搜索双平方数的上界0 <= p,q <= M。
输出:如果没有找到数列,输出`NONE’。
如果找到了,输出一行或多行, 每行由两个整数组成:a,b 这些行应该先按b排序再按a排序(均为升序)。将不会有多于10,000个等差数列。
5 7
1 4
37 4
2 8
29 8
1 12
5 12
13 12
17 12
5 20
2 24
这道题初看思路很好理解,只需要先找到平方数的集合,然后从集合选中数,求差距,不断向上递增,查看长度为n的数列是否在集合中即可。
当m比较小的时候还能快速求解,但当m比较大的时候,由于求解对比的数量大大增加后,就很容超时(就是被这个超时难受的抓头),后来经过初步优化是间隔b最大的取值为(集合最大值-选取的数列首个元素)/ 数列长度,时间优化了一些,但还是不能解决m过大时的超时问题,之后再查看了一些文章后,找到了关键的优化 :if(vi[i]+(vi[j]-vi[i])*(n-1) > vi[len-1])continue;
但由于我用的是vector来存储的元素,在查找的时候还是容易超时。
查询之后发现是vector是动态的分配空间,在查询的时候没有直接分配内存的数组高效。在更改过后,最终还是AC了。
#include<iostream>
#include<algorithm>
#include <cstring>
#include<cmath>
const int maxs=250*250+10;
using namespace std;
typedef struct lie{
int a;
int b;
bool operator < (const lie & d) const{
if (d.b==b) return a<d.a;
return b<d.b;
}
}lie;
int main(){
int n,i,j,m,a,b,len,k,t;
int vi[maxs];
lie l[10000]={-1,-1};
bool vis[maxs*2];
memset(vis,0,sizeof(vis));
scanf("%d%d",&n,&m);
len=0;
for(i=0;i<=m;i++){
for(j=i;j<=m;j++){
if (vis[i*i+j*j]==0){
vi[len++]=i*i+j*j;
vis[i*i+j*j]=1;
}
}
}
sort(vi,vi+len);
t=0;
for(i=0;i<len;i++){
for(j=i+1;j<len;j++){
if(vi[i]+(vi[j]-vi[i])*(n-1) > vi[len-1])continue;
a=vi[j],b=vi[j]-vi[i],k=2;
while(vis[a+b] && a+b<=vi[len-1] && k<n){
k++;
a=a+b;
}
if(k==n){
l[t].a=vi[i];
l[t++].b=b;
}
}
}
if(t==0){
printf("NONE\n");
return 0;
}
sort(l,l+t);
for(i=0;i<t;i++){
printf("%d %d\n",l[i].a,l[i].b);
}
return 0;
}
参考:
https://blog.csdn.net/Gregory99174/article/details/101831680
来源:CSDN
作者:LZ_Squirrel
链接:https://blog.csdn.net/LZ_Squirrel/article/details/104628898