东华OJ基础 54 等差数列

东华OJ基础 54 等差数列

问题描述
一个等差数列是一个能表示成a, a+b, a+2b,…, a+nb (n=0,1,2,3,…) 在这个问题中a是一个非负的整数,b是正整数。

写一个程序来找出在双平方数集合S中长度为n的等差数列。双平方数集合是所有能表示成p2+q2的数的集合。

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

输出说明
如果没有找到数列,输出`NONE’。

如果找到了,输出一行或多行, 每行由两个整数组成:a,b 这些行应该先按b排序再按a排序(均为升序)。

将不会有多于10,000个等差数列。

解答


#include<iostream>
#include<algorithm>
const int maxs=250*250+10;
using namespace std;
struct ans{
    int a;
    int b;
};
int comparation(ans x1, ans x2){
    if(x1.b == x2.b) {
        return x1.a < x2.a;
    }
    return x1.b < x2.b;
}
int main(){
    int N;
    int M;
    scanf("%d %d", &N, &M);
    int vis[250 * 250 + 10] = {0};
    int vi[250 * 250 + 10] = {0};
    ans as[250 * 250 + 10];
    int length = 0;
    for(int i = 0; i <= M; i++) {
        for(int j = i; j <= M; j++) {
            if(vis[i * i + j * j] == 0) {
                vi[length++] = i * i + j * j;
                vis[i * i + j * j] = 1;
            }
        }
    }
    sort(vi, vi + length);
    int index = 0;
    for(int i = 0; i < length; i++) {
        for(int j = i + 1; j < length; j++) {
            if(vi[i] + (N - 1) * (vi[j] - vi[i]) > vi[length - 1]) {
                continue;
            }
            int d = vi[j] - vi[i];
            int a = vi[j];
            int k = 2;
            while(vis[a + d] != 0 && a + d <= vi[length - 1] && k < N) {
                k++;
                a = a + d;
            }
            if(k == N) {
                as[index].a = vi[i];
                as[index].b = d;
                index++;
            }
        }
    }
    if(index == 0) {
        printf("NONE");
    }
    sort(as,as + index, comparation);
    for(int i = 0; i < index; i++) {
        printf("%d %d\n",as[i].a,as[i].b);
    }
	return 0;
}


下面内容来自Chat-GPT 4o

这段代码的目的是在给定的范围内寻找长度为 N 的等差数列,且数列中的元素属于双平方数集合。程序从输入获取要搜索的等差数列长度 N 和搜索的上界 M,然后寻找符合条件的等差数列并输出。若没有找到任何等差数列,则输出 “NONE”。

头文件和常量定义

#include<iostream>
#include<algorithm>
const int maxs = 250 * 250 + 10;
  • #include<iostream>:包含输入输出流库,方便进行输入输出操作。
  • #include<algorithm>:包含常用算法库,如排序函数。
  • const int maxs = 250 * 250 + 10;:定义常量 maxs,表示双平方数的最大值为 250² + 250² = 125000,再加上一个额外的 10,以便于使用数组来存储相关的值。

结构体定义

struct ans{
    int a;
    int b;
};

定义一个结构体 ans,包含两个整数成员 ab。这两个成员分别用于存储等差数列的首项 a 和公差 b

排序比较函数

int comparation(ans x1, ans x2){
    if(x1.b == x2.b) {
        return x1.a < x2.a;
    }
    return x1.b < x2.b;
}

定义了一个比较函数 comparation,用于在排序时比较两个 ans 结构体:

  • 如果 b 相等,则按照 a 升序排列。
  • 否则,按照 b 升序排列。

主函数部分

int main(){
    int N;
    int M;
    scanf("%d %d", &N, &M);
  • 读取输入的两个整数 NM,分别表示等差数列的长度和双平方数的搜索上界。
    int vis[250 * 250 + 10] = {0};
    int vi[250 * 250 + 10] = {0};
    ans as[250 * 250 + 10];
    int length = 0;
  • vis 数组用于标记是否已访问某个双平方数。
  • vi 数组用于存储所有计算出来的双平方数。
  • as 数组用于存储符合条件的等差数列的首项 a 和公差 b
  • length 变量用于记录 vi 数组中双平方数的个数。

生成双平方数

    for(int i = 0; i <= M; i++) {
        for(int j = i; j <= M; j++) {
            if(vis[i * i + j * j] == 0) {
                vi[length++] = i * i + j * j;
                vis[i * i + j * j] = 1;
            }
        }
    }

通过嵌套循环生成所有 p² + q² 形式的双平方数(其中 pq0M)。当找到一个新的双平方数时,将其存入 vi 数组,并更新 vis 数组,标记该数已被访问。

排序双平方数

    sort(vi, vi + length);

vi 数组中的双平方数按升序排序。

寻找等差数列

    int index = 0;
    for(int i = 0; i < length; i++) {
        for(int j = i + 1; j < length; j++) {
            if(vi[i] + (N - 1) * (vi[j] - vi[i]) > vi[length - 1]) {
                continue;
            }
            int d = vi[j] - vi[i];
            int a = vi[j];
            int k = 2;
            while(vis[a + d] != 0 && a + d <= vi[length - 1] && k < N) {
                k++;
                a = a + d;
            }
            if(k == N) {
                as[index].a = vi[i];
                as[index].b = d;
                index++;
            }
        }
    }
  • 外层循环 i 和内层循环 j 用于遍历 vi 数组中的每一对数。
  • 对于每一对数 vi[i]vi[j],计算它们的公差 d = vi[j] - vi[i]
  • 判断从 vi[i] 开始,步长为 d 的数列是否可以构造出长度为 N 的等差数列。
    • 如果无法构造出,跳过当前的 i, j
    • 如果能构造出,检查每一项是否在双平方数集合中,并且小于或等于最大双平方数。
  • 如果成功找到长度为 N 的等差数列,就将首项 vi[i] 和公差 d 存入 as[index]

判断是否找到等差数列

    if(index == 0) {
        printf("NONE");
    }

如果 index 为 0,表示没有找到符合条件的等差数列,输出 “NONE”。

输出结果

    sort(as, as + index, comparation);
    for(int i = 0; i < index; i++) {
        printf("%d %d\n", as[i].a, as[i].b);
    }
  • 使用 sort 函数按照 comparation 函数对 as 数组中的等差数列进行排序。
  • 输出所有找到的等差数列的首项和公差。

程序结束

    return 0;
}

程序结束,返回 0,表示程序成功执行完毕。


总结:

这段代码的目标是通过生成双平方数集合,检查其中是否存在满足特定条件的等差数列。最终输出所有符合条件的等差数列的首项和公差,如果没有找到则输出 “NONE”。

参考文章

进阶45-等差数列

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值