CF1548B(gcd,思维)

CF1548B(gcd,思维)

题意

给定长度为 n 的序列 a,找到最长子段使得该段中任意元素元素满足 aimodm=k。输出其长度

思路

第一眼看这个题的形式不好写,因为 m,k 都不知道。如果知道如下的结论,可以将其转化到好写的形式。

如果 xmodm=ymodm=k,那么 |xy|modm=0

换而言之,如果区间 [l,r] 满足要求,那么它的 差分数组 b 一定是满足上面结论的。此时 k 也就被消去。

问题变为,在差分数组 b 上,找最长子段满足 bimodm=0m2 。这个同余式子就可以很容易转化为整除的式子:m|bi 。显然 m 就是区间 gcd

这个问题可以用 ST表加双指针解决。时间复杂度 O(nlogn)

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<set>
#include<queue>
#include<map>
#include<stack>
#include<string>
#include<random>
#include<iomanip>
#define yes puts("yes");
#define inf 0x3f3f3f3f
#define ll long long
#define linf 0x3f3f3f3f3f3f3f3f
#define ull unsigned long long
#define endl '\n'
#define int long long
#define rep(i,a,n) for(int i = a;i <= n;i++)
#define per(i,n,a) for(int i = n;i >= a;i--)
using namespace std;
mt19937 mrand(random_device{}());
int rnd(int x) { return mrand() % x;}
typedef pair<int,int> PII;
const int MAXN =10 + 2e5 ,mod=1e9 + 7;
template<typename T> struct ST{
    ST(vector<T> a, int n){ // cope with in [0,n] 
        siz = n;
        f.resize(n + 1);
        int t = __lg(n) + 1;
        for(int i= 0;i<=n;i++) f[i].resize(t);
        for(int i = 0; i <= n; i++) f[i][0] = a[i];
        for(int j = 1; j < t; j++) {
            for(int i = 0; i <= n - (1<<j)+1; i++) {
                f[i][j] = __gcd(f[i][j - 1], f[i + (1 << j - 1)][j - 1]);
            }
        }
    }
    T get(int l,int r){
       int k = __lg(r-l+1);
       return __gcd(f[l][k],f[r-(1<<k)+1][k]);
    }     
private:
    int siz = 0;
    vector<vector<T>> f;
};
void solve()
{    
    int n; cin >> n;
    vector<int> a(n + 1);
    rep(i,1,n) cin >> a[i];
    vector<int> b(n + 1);
    rep(i,1,n - 1) b[i] = abs(a[i] - a[i + 1]);
    ST stt(b,n);
    int ans = 1;
    for(int i = 1,j = 1;i < n;i ++) {
        while(j < n && (i > j || stt.get(i,j) > 1)) j ++;
        // b:[i,j] <--> a:[i,j+1]   
        ans = max(ans, j - i + 1);
    }
    cout << ans << endl;
}
signed main()
{
    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);

    int T;cin>>T;
    while(T--)
        solve();

    return 0;
}
posted @   Mxrurush  阅读(15)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示