CF475D CGCDSSQ

Problem

link

给出一个长度为\(n(1<=n<=10^{5})\) 的序列和\(q(1<=q<=3*10^{5})\) 个询问,每个询问输出一行,询问\(gcd(a_l,a_{l+1},...,a_r)=x\)\((i,j)\) 的对数。

Solution

分治好题!我永远喜欢分治!

注意到一个事实:一个连续区间的 \(\gcd\) 一定是单调不增的,且 \(\gcd\) 每次变化至少除 \(2\) ,也就是说 \(\gcd\) 的数量是 \(\log\) 级的,好神奇吧!

那就分治!

考虑怎么统计当前区间的答案:

  1. 取中点 \(mid\)
  2. 从中间向两边统计 \([l,mid],[mid+1,r]\) 两个区间的 \(\gcd\) ,注意到这两段都是单调不增且 \(\log\) 级的,那首先把这些答案扔进 \(map\) 里面,最后暴力枚举两边的 \(\gcd\) ,他俩的 \(\gcd\) 出现个数就是 \(cnt_{l} \times cnt_{r}\)
  3. 递归左右区间。

于是你优美的做完了这道题!

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define Rep(i,a,b) for(int i=(a);i<(b);++i)
#define rrep(i,a,b) for(int i=(a);i>=(b);--i)
using namespace std;
template <typename T>
inline void read(T &x){
    x=0;char ch=getchar();bool f=0;
    while(ch<'0'||ch>'9'){if(ch=='-')f=1;ch=getchar();}
    while(ch>='0'&&ch<='9')x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
    if(f)x=-x;
}
template <typename T,typename ...Args>
inline void read(T &tmp,Args &...tmps){read(tmp);read(tmps...);}
typedef long long ll;
const int N = 1e5 + 5;
map<int,ll>ans;
int n,m,a[N];
void solve(int l,int r){
    if(l == r){
        ans[a[l]]++;
        return;
    }
    int mid = (l + r) >> 1;
    solve(l,mid);solve(mid+1,r);
    int last = a[mid],now = a[mid],cnt = 0;
    vector<pair<int,int>>v[2];
    rrep(i,mid,l){
        now = __gcd(now,a[i]);
        if(now != last){
            v[0].push_back({last,cnt});
            last = now;cnt = 1;
        }
        else ++cnt;
    }
    v[0].push_back({last,cnt});
    last = now = a[mid+1],cnt = 0;
    rep(i,mid+1,r){
        now = __gcd(now,a[i]);
        if(now != last){
            v[1].push_back({last,cnt});
            last = now;cnt = 1;
        }
        else ++cnt;
    }
    v[1].push_back({last,cnt});
    for(auto t1 : v[0])for(auto t2 : v[1])
    ans[__gcd(t1.first,t2.first)] += 1ll * t1.second * t2.second;
}
signed main(){
    read(n);
    rep(i,1,n)read(a[i]);
    solve(1,n);
    read(m);
    while(m--){
        int x;
        read(x);
        printf("%lld\n",ans[x]);
    }
}
posted @ 2022-09-14 20:29  Xu_brezza  阅读(25)  评论(0编辑  收藏  举报