17多校6 HDU - 6102

题意:给一个排列p,m次查询l,r,\(\sum_{i=l}^r\sum_{j=i+1}^r\sum_{k=j+1}^r[gcd(p_i,p_j)==p_k]p_k\)
题解:离线,枚举右端点,对于每个数在i位置的数\(p_i\),考虑前面所有是\(p_i\)的倍数的位置,假设是\(t_1,t_2,...,t_x\)从后往前枚举,那么对于\(t_j\)来说,所有在\(t_j\)到\(i\)之间的位置,假设有k个位置和\(t_j\)gcd为\(a_i\),那么对于右端点在i,左端点在\(t_j\)左侧的查询,都要加上该贡献,就是\(k*a_i\),这里把贡献都加到树状数组上,对于求\(gcd(a_{t_j},a_x)=a_i\)的个数考虑反演,即\(\mu(p*a_i)*cnt_{p*a_i}\).在从后往前枚举的时候加到cnt中即可,复杂度\(O(nlog^2n)\)

//#pragma GCC optimize(2)
//#pragma GCC optimize(3)
//#pragma GCC optimize(4)
//#pragma GCC optimize("unroll-loops")
//#pragma comment(linker, "/stack:200000000")
//#pragma GCC optimize("Ofast,no-stack-protector")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#include<bits/stdc++.h>
//#include<bits/extc++.h>
#define fi first
#define se second
#define db double
#define mp make_pair
#define pb push_back
#define mt make_tuple
#define pi acos(-1.0)
#define ll long long
#define vi vector<int>
#define mod 1000000007
#define ld long double
//#define C 0.5772156649
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1
#define sqr(x) ((x)*(x))
#define pll pair<ll,ll>
#define pil pair<int,ll>
#define pli pair<ll,int>
#define pii pair<int,int>
#define ull unsigned long long
#define bpc __builtin_popcount
#define base 1000000000000000000ll
#define fin freopen("a.in","r",stdin)
#define fout freopen("a.txt","w",stdout)
#define fio ios::sync_with_stdio(false);cin.tie(0)
#define mr mt19937 rng(chrono::steady_clock::now().time_since_epoch().count())
inline ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
inline void sub(ll &a,ll b){a-=b;if(a<0)a+=mod;}
inline void add(ll &a,ll b){a+=b;if(a>=mod)a-=mod;}
template<typename T>inline T const& MAX(T const &a,T const &b){return a>b?a:b;}
template<typename T>inline T const& MIN(T const &a,T const &b){return a<b?a:b;}
inline ll qp(ll a,ll b){ll ans=1;while(b){if(b&1)ans=ans*a%mod;a=a*a%mod,b>>=1;}return ans;}
inline ll qp(ll a,ll b,ll c){ll ans=1;while(b){if(b&1)ans=ans*a%c;a=a*a%c,b>>=1;}return ans;}

using namespace std;
//using namespace __gnu_pbds;

const ull ba=233;
const db eps=1e-5;
const ll INF=0x3f3f3f3f3f3f3f3f;
const int N=100000+10,maxn=500000+10,inf=0x3f3f3f3f;

vi f[N],fac[N];
int cnt[N],a[N],pos[N],mu[N];
struct bit{
    ll sum[N];
    int len;
    void init(int n)
    {
        len=n;
        for(int i=1;i<=n;i++)sum[i]=0;
    }
    void update(int i,ll v){for(;i<=len;i+=i&(-i))sum[i]+=v;}
    ll query(int i){ll ans=0;for(;i;i-=i&(-i))ans+=sum[i];return ans;}
}b;
vector<pii>q[N];
ll ans[N];
int main()
{
    mu[1]=1;
    for(int i=1;i<N;i++)
    {
        for(int j=i;j<N;j+=i)f[j].pb(i);
        for(int j=2*i;j<N;j+=i)mu[j]-=mu[i];
    }
    for(int i=1;i<N;i++)if(mu[i]!=0)for(int j=i;j<N;j+=i)fac[j].pb(i);
    int T;scanf("%d",&T);
    while(T--)
    {
        int n,m;scanf("%d%d",&n,&m);
        b.init(n);
        for(int i=1;i<=n;i++)scanf("%d",&a[i]),pos[a[i]]=i,q[i].clear();
        for(int i=1;i<=m;i++)
        {
            int l,r;scanf("%d%d",&l,&r);
            q[r].pb(mp(l,i));
        }
        for(int i=1;i<=n;i++)
        {
            vi v;
            for(int j=2*a[i];j<=n;j+=a[i])if(pos[j]<i)v.pb(pos[j]);
            sort(v.begin(),v.end(),greater<int>());
            for(int x:v)
            {
                ll te=0;
                for(int y:fac[a[x]/a[i]])te+=cnt[y]*mu[y];
                te=te*a[i];
                b.update(1,te);b.update(x+1,-te);
                for(int y:f[a[x]/a[i]])cnt[y]++;
            }
            for(int x:v)for(int y:f[a[x]/a[i]])cnt[y]--;
            for(pii x:q[i])ans[x.se]=b.query(x.fi);
        }
        for(int i=1;i<=m;i++)printf("%lld\n",ans[i]);
    }
    return 0;
}
/********************

********************/
上一篇:C++#pragma once


下一篇:堆喷图解