1246. 等差数列(数论,gcd)

https://www.acwing.com/problem/content/1248/
求最短的序列,我们知道整个序列的其中几个数
数列不确定,公差不确定,需要确定参数
总项数为(数列末端-数列首端)/d 求出中间有多少个d, 然后再加1就得到总项数了
要使这个公式最小,那么数列末端要尽可能小,数列首端要尽可能大,数列的公差也要最大,
由于要求最小项数,那么数列末端也就是Amax,数列首端也就是Amin
那么就可以确定数列首端,即a[1]了,那么给出的几个数都是这样组成的: a[1] + nd
那么它们与a[1]的差就是d的倍数,需要满足d最大,那么就是要在这些差中取最大公约数

关于这题的思路
感觉这些比较难想到的题都可以采用逆向思维去想,关键是要列出(数列末端-数列首端)/d+1这个式子,分析分母何时最大,分子何时最小,是怎么想到要求最大公约数的
比如说:求一个d,d一定是满足每个数与a[1]的差的约数的,反过来想,如果这个d已经是所有差的约数了,那么输入给出的这几个数,必定是这个最短的数列里的几个数
即最短数列一定包含给出的几个数,但是这个最短数列还不一定是最短,得让这个d最大才是最短的数列,要满足这个数列包含输入的几个数,就要保证d是所有数的约数,且最大,即求最大公约数

#include<iostream>
#include<algorithm>


using namespace std;

const int N = 1e5+10;
int a[N],n;
int d=0;

int gcd(int a,int b)
{
    return b ? gcd(b,a%b) : a ;
}

int main()
{
    cin >> n;
    for(int i=1;i<=n;i++) cin >> a[i];
    sort(a+1,a+n+1);
    for(int i=2;i<=n;i++) d=gcd(d,a[i]-a[1]);
    if(d==0) cout << n << endl;
    else cout << (a[n]-a[1])/d+1 << endl;
    return 0;
}

 

posted @   风乐  阅读(28)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
点击右上角即可分享
微信分享提示