USACO1.4.3 Arithmetic Progressions 等差数列 解题报告(枚举)

本文介绍了一个算法挑战,旨在找出特定长度的等差数列,其中数列的项都是双平方数(即可以表示为两个平方数之和)。通过预计算所有可能的双平方数,并使用暴力搜索策略,文章提供了一种有效的方法来解决问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Description

一个等差数列是一个能表示成a, a+b, a+2b,..., a+nb (n=0,1,2,3,...)的数列。 在这个问题中a是一个非负的整数,b是正整数。写一个程序来找出在双平方数集合(双平方数集合是所有能表示成p^2+q^2的数的集合)S中长度为n的等差数列。

Input

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

Output

如果没有找到数列,输出`NONE'。 如果找到了,输出一行或多行, 每行由二个整数组成:a,b。 这些行应该先按b排序再按a排序。 所求的等差数列将不会多于10,000个。

Sample Input

5
7 

Sample Output

1 4
37 4
2 8
29 8
1 12
5 12
13 12
17 12
5 20
2 24

 

 

这里需要注意M<=250,所以所有的种类数只有250^2 = 62500,对于长度至多为25的数据完全可以暴力解决

#include <map>
#include <cmath>
#include <cstdio>
#include <string>
#include <cstring>
#include <iostream>
#include <algorithm>
#define lowbit(a) (a&(-a))
#define _mid(a,b) ((a+b)/2)
#define _mem(a,b) memset(a,0,(b+3)<<2)
#define fori(a) for(int i=0;i<a;i++)
#define forj(a) for(int j=0;j<a;j++)
#define ifor(a) for(int i=1;i<=a;i++)
#define jfor(a) for(int j=1;j<=a;j++)
#define mem(a,b) memset(a,b,sizeof(a))
#define IN freopen("in.txt","r",stdin)
#define OUT freopen("out.txt","w",stdout)
#define IO do{\
    ios::sync_with_stdio(false);\
    cin.tie(0);\
    cout.tie(0);}while(0)
using namespace std;
typedef long long ll;
const int maxn =  5*1e6+10;
const int INF = 0x3f3f3f3f;
const int inf = 0x3f;
const double EPS = 1e-7;
const double Pi = acos(-1);
const int MOD = 1e9+7;
bool a[maxn];
bool use[maxn];
int num[maxn];
int main() {
    //IN;
    int k  = 0;
    int Max = -INF;
    int n,m;
    cin >> n >> m;
    fori(m+1)        //存下所有q*q+p*p的组合
    forj(i+1) {
        if(!a[i*i+j*j]) {
            num[k++] = i*i+j*j;
            a[i*i+j*j] = true;
            Max = max(Max,num[k-1]);
        }
    }
    sort(num,num+k);
    int d;
    bool res = false;
    for(int j=1; j*(n-1)<=Max; j++) {   //暴力求解即可
        for(int i=0; i<k; i++) { 
            int step = 1;
            d = num[i];
            while(a[d+j]&&step<n) {
                d += j;
                step ++;
            }
            if(step>=n){
                res = true;
                cout << num[i] <<" "<< j << endl;
            }
        }
    }
    if(!res)
        cout <<"NONE"<<endl;
    return 0;
}

 

转载于:https://www.cnblogs.com/bestsort/p/10588838.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值