ariprog-section1.4

题目大意

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

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值