进阶45-等差数列

你离开我真会死。 提交于 2020-03-03 15:51:05

一个等差数列是一个能表示成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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!