P1214 [USACO1.4]等差数列 Arithmetic Progressions
题目描述
一个等差数列是一个能表示成a, a+b, a+2b,..., a+nb (n=0,1,2,3,...)的数列。
在这个问题中a是一个非负的整数,b是正整数。写一个程序来找出在双平方数集合(双平方数集合是所有能表示成p的平方 + q的平方的数的集合,其中p和q为非负整数)S中长度为n的等差数列。
输入格式
第一行: N(3<= N<=25),要找的等差数列的长度。
第二行: M(1<= M<=250),搜索双平方数的上界0 <= p,q <= M。
输出格式
如果没有找到数列,输出`NONE'。
如果找到了,输出一行或多行, 每行由二个整数组成:a,b。
这些行应该先按b排序再按a排序。
所求的等差数列将不会多于10,000个。
输入输出样例
输入 #1
5 7
输出 #1
1 4 37 4 2 8 29 8 1 12 5 12 13 12 17 12 5 20 2 24
说明/提示
题目翻译来自NOCOW。
USACO Training Section 1.4
思路
先用桶排序(不会爆),然后再把数集中起来,搜索一下即可。 两重循环中还要一些判断和剪枝,让程序跑得更快。
代码:
#include<cmath> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; const int N=125010; bool num[N]; int s[N],tot; int n,m,p,q,cnt; int main () { scanf("%d%d",&n,&m); memset(num,false,sizeof(num)); for(int i=0; i<=m; i++) for(int j=0; j<=m; j++) num[i*i+j*j]=true; tot=0; for(int i=0; i<=125000; i++) if(num[i]) s[++tot]=i; cnt=0; for(int b=1; b<s[tot]; b++) for(int i=1; i<tot-1; i++) { if(s[i]+(n-1)*b>s[tot]) break; int flag; for(flag=2; flag<=n; flag++) if(!num[s[i]+(flag-1)*b]) break; if(flag==n+1&&num[s[i]+(n-1)*b]) { printf("%d %d\n",s[i],b); cnt++; } } if(!cnt) printf("NONE\n"); return 0; }