专栏文章

题解:P14221 [ICPC 2024 Kunming I] 学而时习之

P14221题解参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@mingcj6f
此快照首次捕获于
2025/12/02 01:57
3 个月前
此快照最后确认于
2025/12/02 01:57
3 个月前
查看原文

思路:

根据题意,需要尝试所有可能的区间 (l,r)(l , r),将该区间内的元素都加 kk 后,计算整个序列的最大公因数。
但是但是,如果直接模拟处理,时间肯定就炸飞了。
为了高效计算,可以预处理两个辅助数组:
pre_gcdipre\_gcd_i:表示前 ii 个元素的最大公因数。
last_gcdilast\_gcd_i:表示从 iinn 所有元素的最大公因数。
然后遍历每个可能的区间起点 ii,若前缀最大公因数无变化则跳过。
ii 开始扩展区间终点 jj,计算区间 (i,j)(i , j) 中的数加 kk 后的最大公因数(记为 ss)。
结合 ss 与区间右侧的后缀最大公因数,得到整个序列的最大公因数,并更新答案。
完结撒花~

CodeCPP
#include<bits/stdc++.h>
using namespace std ;
const int maxn=3e5+5;
int n;
long long k,a[maxn],last_gcd[maxn],pre_gcd[maxn],s;
long long ans=0;
long long gcd (long long a, long long last_gcd) { 
	if (last_gcd==0) return a;
	if (a%last_gcd==0) return last_gcd;
	return gcd(last_gcd,a%last_gcd);
}
int main () {
    int t;
    cin>>t;
    while (t--) {
        cin>>n>>k;
        for (int i=1;i<=n;i++) cin>>a[i];
        for (int i=1;i<=n;i++) pre_gcd[i]=gcd(pre_gcd[i-1],a[i]);
        last_gcd[n+1]=0;
        for(int i=n;i>=1;i--) last_gcd[i]=gcd(last_gcd[i+1],a[i]);
        ans=pre_gcd[n];
        for (int i=1;i<=n;i++) {
            if (pre_gcd[i]==pre_gcd[i-1]) continue;
            s=pre_gcd[i-1];
            for (int j=i;j<=n;j++) {
                s=gcd(s,a[j]+k);
                ans =max(ans,gcd(s,last_gcd[j+1]));
            }
        }
        cout<<ans<<"\n";
    }
    return 0;
}

评论

0 条评论,欢迎与作者交流。

正在加载评论...