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;
}

浙公网安备 33010602011771号