17多校6 HDU - 6102

Posted acjiumeng

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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;

/********************

********************/

以上是关于17多校6 HDU - 6102的主要内容,如果未能解决你的问题,请参考以下文章

HDU 6055 17多校 Regular polygon(计算几何)

HDU 6124 17多校7 Euler theorem(简单思维题)

HDU 6045 17多校2 Is Derek lying?

HDU 6050 17多校2 Funny Function(数学+乘法逆元)

HDU 6077 17多校4 Time To Get Up 水题

HDU 6090 17多校5 Rikka with Graph(思维简单题)