USACO:1.4.3 Arithmetic Progressions 等差数列 解析

1.4.3 Arithmetic Progressions 等差数列 解析

题目描述:

一个等差数列是一个能表示成a, a+b, a+2b,..., a+nb (n=0,1,2,3,...)

在这个问题中a 是一个非负的整数,b 是正整数.
写一个程序来找出在双平方数集合S 中长度为n 的等差数列.
双平方数集合是所有能表示成p2+q2 的数的集合.
PROGRAM NAME: ariprog
INPUT FORMAT
第一行: N(3<= N<=25),要找的等差数列的长度.
第二行: M(1<= M<=250),搜索双平方数的上界0 <= p,q <= M.
SAMPLE INPUT (file ariprog.in)
5
7
OUTPUT FORMAT
如果没有找到数列,输出`NONE'.
如果找到了,输出一行或多行, 每行由于二个整数组成:a,b

这些行应该先按b 排序再按a 排序.
将不会有只多于10,000 个等差数列.
SAMPLE OUTPUT (file ariprog.out)
1 4
37 4
2 8
29 8
1 12
5 12
13 12
17 12
5 20
2 24

解题思路:

    这个题目很简单,就是采用暴力求解,枚举出所有可能的结果。关键是通过剪枝,降低运行时间。。。

    首先,我们用一个布尔数组bqsuaretemp[i]记录i是否是bisquare ;同时为了加速,用bsquare[]有序记录所有的bisquare(除去中间的空位置,对付大数据时很有用)。然后就很简单了,我们通过枚举bsquare中的两个数a=a0=bsquare[x]、a1=bsquare[y],其中a1>a0,公差b=a1-a0;并连续算N-1个数看是否在布尔数组bsquare1[]中。

    注意,要求按b排序,再按a二次排序。

    提示:利用约束a+(N-1)*b<=bsquare[max] 来剪枝。。。

/*
ID:pen_wan1
LANG:C++
TASK:ariprog
*/
#include <iostream>
#include <stdio.h>
#include<algorithm>
#include<assert.h>

using namespace std;
typedef struct  
{ int a;
int b;
}ariprog;

ariprog	Ariprog[10000];

int bsquaretemp[130000+10],
bsquare[130000+10],z=0;

int cmp(int i,int j)
{  return  Ariprog[i].b<Ariprog[j].b;}

int main(){
	FILE *fin,*fout ;
	fin=fopen("ariprog.in","r");
	fout=fopen("ariprog.out","w");
	assert(fin!=NULL&&fout!=NULL);
	
	int N,M;
	int a,b,c,ok;
	int i,j;
	int x,y;
	int id=0,k=0;
	fscanf(fin,"%d %d",&N,&M);
	//利用布尔数组bqsuaretemp[i]记录i是否是bisquare
	for (i=0;i<=M;i++)
		for (j=i;j<=M;j++)
		{ bsquaretemp[i*i+j*j]=1;}
	//用bsquare[]有序记录所有的bisquare(除去中间的空位置,对付大数据时很有用)	
	for (i=0;i<=2*M*M;i++)
	{ if(bsquaretemp[i]==1)
		bsquare[id++]=i;}		
		id--;
	//枚举bsquare中的两个数a=a0=bsquare[x]、a1=bsquare[y],其中a1>a0,公差b=a1-a0;并连续算N-1个数看是否在布尔数组bsquare1[]中。	
	for (x=0;x<=id;x++){
		a=bsquare[x];
		for (y=x+1;y<=id;y++){
			b=bsquare[y]-a;
			if(a+(N-1)*b<=bsquare[id]) 
			{				
				for (i=0;i<N;i++){  
					c=a+i*b;
					ok=(bsquaretemp[c]?1:0);
					if (!ok)	break;
					}
					if (ok)	{ Ariprog[k].a=a;Ariprog[k++].b=b;}
				}
			else break;
			}
		}
		
	int st[100];
	for (i=0;i<k;i++) st[i]=i; 
	//建立按b排序的索引	
	sort(st,st+k,cmp);
		
	for ( i=0;i<k;i++){
		fprintf(stdout,"%d %d\n",Ariprog[st[i]].a,Ariprog[st[i]].b);
		}
		
	if(k==0)	fprintf(stdout,"NONE\n");
		
	return 0;	
}


         由于自身是初学者,编程能力有限,未达到专业程序员的水平,可能误导大家,请大家甄读;文字编辑也一般,文中会有措辞不当。博文中的错误和不足敬请读者批评指正。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

蓝亦

感谢博主辛勤的付出

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值