[国家集训队]和与积

link\color{deeppink}link

给出 nn,统计满足下面条件的数对 (a,b)(a,b) 的个数:

  1. 1≤a<b≤n1\le a < b \le n
  2. a+b ∣ a×ba+b~\vert ~a\times b

∑i,j[i+j ∣ ij][1≤i<j≤n]=∑i,j,d,s,t[d=gcd⁡(i,j)][i=sd][j=td][1≤sd<td≤n][d(s+t) ∣ d2st][s⊥t]\sum_{i,j}[i+j~\vert~ij][1\le i<j\le n]\\ =\sum_{i,j,d,s,t}[d=\gcd(i,j)][i=sd][j=td][1\le sd<td\le n][d(s+t)~\vert~d^2st][s\bot t]

注意到 [d(s+t) ∣ d2st][d(s+t)~\vert~d^2st] 可以化为 [s+t ∣ dst][s+t~\vert~dst],而 s⊥ts\bot t,故 s+t∤sts+t \nmid st,所以可以化为 [s+t ∣ d][s+t~\vert~d]。

=∑s,t,d[1≤sd<td≤n][s+t ∣ d][s⊥t]=∑s,t,d,k[d=k(s+t)][s⊥t][1≤sk(s+t)<tk(s+t)≤n][k≥1]=∑s,t,k[s⊥t][k∈[1,nt(s+t)]][s<t]=∑s,t⌊nt(s+t)⌋[s⊥t][s<t]=∑s,t,k⌊nt(s+t)⌋[k ∣ s][k ∣ t][s<t]μ(k)=\sum_{s,t,d}[1\le sd<td\le n][s+t~\vert~d][s\bot t]\\ =\sum_{s,t,d,k}[d=k(s+t)][s\bot t][1\le sk(s+t)<tk(s+t)\le n][k\ge 1 ]\\ =\sum_{s,t,k}[s\bot t][k\in[1,\frac{n}{t(s+t)}]][s<t]\\ =\sum_{s,t}\lfloor\frac{n}{t(s+t)} \rfloor[s\bot t][s<t]\\ =\sum_{s,t,k}\lfloor\frac{n}{t(s+t)} \rfloor[k~\vert~s][k~\vert~t][s<t]\mu(k)\\

换成上下界的形式

∑t=1n∑s=1t−1∑k ∣gcd⁡(s,t)⌊nt(s+t)⌋μ(k)=∑k=1nμ(k)∑t=1⌊nk⌋∑s=1t−1⌊nk2t(s+t)⌋\sum_{t=1}^n\sum_{s=1}^{t-1}\sum_{k~\vert\gcd(s,t)}\lfloor\frac{n}{t(s+t)}\rfloor\mu(k)\\ =\sum_{k=1}^n\mu(k) \sum_{t=1}^{\lfloor\frac{n}{k}\rfloor}\sum_{s=1}^{t-1}\lfloor\frac{n}{k^2t(s+t)}\rfloor

注意到 k2k^2 和 t2t^2 应小于等于 nn,否则后面的式子变为 00。

=∑k=1nμ(k)∑t=2nk∑s=t+12t−1⌊⌊nk2t⌋s⌋=\sum_{k=1}^{\sqrt {n}} \mu(k) \sum_{t=2}^{\frac{\sqrt n}{k}}\sum_{s=t+1}^{2t-1}\lfloor \frac{\lfloor\frac{n}{k^2t}\rfloor}{s} \rfloor

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=sqrt(3e7)+555500;

int n,mu[N],ans,a[N],cnt,pri[N],m;

void init()
{
	m=sqrt(n);mu[1]=1;
	for(int i=2;i<=m;i++)
	{
		if(!a[i])pri[++cnt]=i,mu[i]=-1;
		for(int j=1;j<=cnt&&pri[j]*i<=m;j++)
		{
			a[i*pri[j]]=1;
			if(i%pri[j]==0)break;
			mu[i*pri[j]]=-mu[i];
		}
	}
}

int find(int x,int L,int R)
{
//	cout<<x<<' '<<L<<' '<<R<<' ';
	int ans=0;R=min(R,x);
	for(int i=L;i<=R;i++)
	{
		int val=x/i,r=min(R,x/val);
		ans+=(r-i+1)*val;
		i=r;
	}
//	cout<<ans<<'\n';
	return ans;
}

main()
{
	cin>>n;init();
	for(int k=1;k<=m;k++)if(mu[k])
	{
//		cout<<k<<' '<<mu[k]<<'\n';
		for(int t=2;t<=m/k;t++)
		{
			ans+=find(n/(k*k*t),t+1,2*t-1)*mu[k];
		}
	}
	cout<<ans;
}