题目大意
一个等差数列是一个能表示成a, a+b, a+2b,..., a+nb (n=0,1,2,3,...)的数列。
在这个问题中a是一个非负的整数,b是正整数。写一个程序来找出在双平方数集合(双平方数集合是所有能表示成p的平方 + q的平方的数的集合,其中p和q为非负整数)S中长度为n的等差数列。
输入格式
line 1: N(3<= N<=25),要找的等差数列的长度。
line 2: M(1<= M<=250),搜索双平方数的上界0 <= p,q <= M。
输出格式
如果没有找到数列,输出“NONE”。
如果找到了,输出一行或多行, 每行由二个整数组成:a,b。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
题解
遍历所有情况,判断是否满足条件即可。(关键是优化,不然你很容易超时),本题中一个重要的优化技巧,判断一个数是否是双平方数,可以将所有双平方数当作数组下标,将相应的数组元素负值一,其余负值零。这样只要需要判断的书也放在数组下标,判断该元素是否为1即可。
代码
#include<stdio.h>
int N=0,M=0,I=0,bo[300000]={0};
long int e[10010]={0},f[10010]={0},number[35000];
int square(long int i)
{
int p=0,q=0;
for(p=0;p<=M;p++)
for(q=p;q<=M;q++)
{
if(i==(p*p+q*q))
return 1;
}
return 0;
}
int main()
{
int flag=0,i=0,j=0,k=0,g=0,x=0,I=0;
long int a=0,b=0,temp;
scanf("%d %d",&N,&M);
int p=0,q=0;
for(p=0;p<=M;p++)
for(q=p;q<=M;q++)
{
bo[p*p+q*q]=1;
}
for(g=0;g<300000;g++)
{
if(bo[g]==1)
{
number[I]=g;
I++;
}
}
for(g=0;g<I;g++)
{
a=number[g];
for(b=1;b<=2*M*M/(N-1);b++)
{
flag=1;
for(i=0;i<N;i++)
if(bo[a+b*i]==0)
{
flag=0;
break;
}
if(flag==1)
{
e[k]=a;
f[k]=b;
k++;
}
}
}
if(k==0)
{
printf("NONE\n");
return 0;
}
for(i=0;i<k;i++)
for(j=0;j<k-i-1;j++)
{
if(f[j]>f[j+1])
{
temp=f[j];
f[j]=f[j+1];
f[j+1]=temp;
temp=e[j];
e[j]=e[j+1];
e[j+1]=temp;
}
}
for(i=0;i<k;i++)
for(j=0;j<k-i-1;j++)
{
if(f[j]==f[j+1]&&e[j]>e[j+1])
{
temp=f[j];
f[j]=f[j+1];
f[j+1]=temp;
temp=e[j];
e[j]=e[j+1];
e[j+1]=temp;
}
}
printf("%ld %ld\n",e[0],f[0]);
for(i=1;i<k;i++)
{if(e[i]==e[i-1]&&f[i]==f[i-1]) continue;
printf("%ld %ld\n",e[i],f[i]);}
return 0;
}