Advertisement

[USACO1.4]等差数列 Arithmetic Progressions

阅读量:

题目:

一种称为能够表示为a,\ a+b,\ a+2b,\ldots,\ a+nb\ (其中n=0, 1, 2, 3,\ldots)的一种序列。
在题目中a是非负整数值而b是正整数值。
开发一个程序以识别在集合S中的长度为n且具有特定特征的所有等差序列。
双平方数组合是由所有满足形式p^2 + q^2\ (其中p\ 和q\ 均为非负值)的数量所构成的一个集合。

输入格式:

第一行: N(3<= N<=25),要找的等差数列的长度。
第二行: M(1<= M<=250),搜索双平方数的上界0 <= p,q <= M。

输出格式:

若无法确定数列,则应输出`NONE’。
一旦发现有多个解,则需依次列出所有解的坐标点,并以有序对的形式表示为(a_i,b_i)。
为了确保结果的一致性与规范性,在排序时应当首先按照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

思路:

为了降低计算复杂度,在预处理阶段我们需要确定第i个元素是否能表示为p^{2} + q^{2}的形式。
进一步确定在序列中排在第l位的元素是否符合该条件。
ans[i]代表第i个元素是否满足条件,则其值可取1或0。
在枚举可能的长度和起点时,需对结果进行优化处理以提高效率。
最后对所有候选方案进行验证以确保其合法性。

代码:

复制代码
    # include<cstdio>
    # include<cstdlib>
    # include<iostream>
    # include<algorithm>
    using namespace std;
    int ans[1000100],f[1000000];
    int main(){
    int n,m,p,q,i,l=0,j,k,d1=0;
    scanf("%d%d",&n,&m);//输入
    for(p=0;p<=m;p++)
        for(q=p;q<=m;q++){
            ans[p*p+q*q]=1;//将可以表示为q*q+p*p的数标记为一
        }
        l=0;
    for(i=0;i<=m*m+m*m;i++) {
        l+=ans[i];
        if(ans[i]){f[l]=i;}//求出第l个
    }
    for(j=1;j<=m*m*2/(n-1);j++){//枚举长度
        for(i=1;i<=l;i++){//枚举起点
            if(f[i]+j*(n-1)>m*m*2)break;//如果已大于最大值就退出
            int c=1,d=f[i];
            for(k=1;k<=n-1;k++){
                d=d+j;//枚举每一项
                if(!ans[d]){//如果不是就退出
                    c=0;
                    break;
                }
            }
            if(c){d1=1;printf("%d %d\n",f[i],j);}//判断输出
        }
    }
    if(d1==0)printf("NONE\n");//如果没有合法序列输出NONE
    return 0;
    }
    
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
    
    AI写代码

全部评论 (0)

还没有任何评论哟~