Kaosar and Counting#12328

Kaosar and Counting (Талдоо)

Problem Author:

AlKaosar Hussain

Prepared by:

Hasan Saleh (MathModel)

Edited by:

Hasan Saleh (MathModel)

Solution

We count triplets (a,b,c) with 1\le a,b,c\le n that are three consecutive terms of an arithmetic progression, pairwise distinct, and satisfy \gcd(a,b,c)=1.

Since (a,b,c) are consecutive in an arithmetic progression, there exist integers and d\ge1 such that

(a,b,c)=(x-d,x,x+d).

The bounds imply

d+1\le x\le n-d, \qquad d\le \frac{n-1}{2}.

Observe that

\gcd(x-d,x,x+d)=\gcd(x,d),

because \gcd(x-d,x)=\gcd(x,d) and \gcd(x,x+d)=\gcd(x,d). Hence the condition \gcd(a,b,c)=1 is equivalent to \gcd(x,d)=1.

For a fixed , let A=n-2d. Then ranges over consecutive integers, and the number of valid centers is

\sum_{k\mid d}\mu(k)\left\lfloor\frac{A}{k}\right\rfloor,

by Möbius inversion. Summing over all directly is too slow, so we use prefix sums of the Möbius function. Let

M(t)=\sum_{i=1}^{t}\mu(i).

We iterate in blocks where both

A=\left\lfloor\frac{n}{d}\right\rfloor \quad\text{and}\quad J=\left\lfloor\frac{n-1}{2d}\right\rfloor

remain constant. For such a block d\in[l,r], the total contribution equals

\big(JA-J(J+1)\big)\cdot\big(M(r)-M(l-1)\big).

Summing these contributions over all blocks gives the number of pairs with x-d,x,x+d valid and \gcd(x,d)=1.

Finally, each valid pair produces two ordered triplets,

(x-d,x,x+d)\quad\text{and}\quad(x+d,x,x-d),

so we multiply the result by .

The Möbius function and its prefix sums are precomputed up to 10^6 in time. Each test case is processed in O(\sqrt{n}), which easily satisfies the constraints.

#include <bits/stdc++.h>
using namespace std;
#define int long long

const int N=1000000;

int mu[N+1],pm[N+1];
int p[N],pc;
bool c[N+1];

inline int M(int x){
    if(x<=0)return 0;
    return pm[x];
}

void precalc(){
    mu[1]=1;
    for(int i=2;i<=N;i++){
        if(!c[i]){
            p[pc++]=i;
            mu[i]=-1;
        }
        for(int j=0;j<pc;j++){
            int x=p[j];
            if(i*x>N)break;
            c[i*x]=1;
            if(i%x==0){
                mu[i*x]=0;
                break;
            }
            mu[i*x]=-mu[i];
        }
    }
    for(int i=1;i<=N;i++)pm[i]=pm[i-1]+mu[i];
}

void solve(){
    int n;cin>>n;
    int lim=(n-1)/2;
    int ans=0;
    for(int l=1;l<=lim;){
        int A=n/l;
        int J=(n-1)/(2*l);
        int r=min({n/A,(n-1)/(2*J),lim});
        ans+=(J*A-J*(J+1))*(M(r)-M(l-1));
        l=r+1;
    }
    cout<<(ans*2)<<"\n";
}

signed main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    precalc();
    int t=1;cin>>t;
    while(t--)solve();
}