正题
题目链接:http://www.ybtoj.com.cn/contest/122/problem/3
题目大意
S(i)S(i)S(i)表示iii的约数个数,QQQ次询问给出n,mn,mn,m求
∑a=1n∑b=1mS(a2)×S(b2)×S(a×b)\sum_{a=1}^n\sum_{b=1}^mS(a^2)\times S(b^2)\times S(a\times b)a=1∑nb=1∑mS(a2)×S(b2)×S(a×b)
1≤Q≤104,1≤n,m≤2×1051\leq Q\leq 10^4,1\leq n,m\leq 2\times 10^51≤Q≤104,1≤n,m≤2×105
解题思路
前面的推式子挺套路的
首先我们要搞定S(n2)S(n^2)S(n2)这个东西,一个经典的结论就是S(n×m)=∑i∣n∑j∣m[gcd(i,j)=1]S(n\times m)=\sum_{i|n}\sum_{j|m}[gcd(i,j)=1]S(n×m)=∑i∣n∑j∣m[gcd(i,j)=1]。莫反一下就有
S(a×b)=∑d∣(a×b)μ(d)∑i×d∣a∑j×d∣b1S(a\times b)=\sum_{d|(a\times b)}\mu(d)\sum_{i\times d|a}\sum_{j\times d|b}1S(a×b)=d∣(a×b)∑μ(d)i×d∣a∑j×d∣b∑1
所以就有
S(n2)=∑d∣nμ(d)S(nd)2S(n^2)=\sum_{d|n}\mu(d)S(\frac{n}{d})^2S(n2)=d∣n∑μ(d)S(dn)2
用线性筛筛出前面的SSS,然后O(nlogn)O(n\log n)O(nlogn)求出h(n)=S(n2)h(n)=S(n^2)h(n)=S(n2)
然后化一下式子
∑a=1n∑b=1mh(a)×h(b)∑i∣a∑j∣b[gcd(i,j)=1]\sum_{a=1}^n\sum_{b=1}^mh(a)\times h(b)\sum_{i|a}\sum_{j|b}[gcd(i,j)=1]a=1∑nb=1∑mh(a)×h(b)i∣a∑j∣b∑[gcd(i,j)=1]
∑d=1μ(d)(∑d∣i∑i∣ah(a))(∑d∣j∑j∣bh(b))\sum_{d=1}\mu(d)(\sum_{d|i}\sum_{i|a}h(a))(\sum_{d|j}\sum_{j|b}h(b))d=1∑μ(d)(d∣i∑i∣a∑h(a))(d∣j∑j∣b∑h(b))
∑d=1μ(d)(∑d∣aS(ad)h(a))(∑d∣bS(bd)h(b))\sum_{d=1}\mu(d)(\sum_{d|a}S(\frac{a}{d})h(a))(\sum_{d|b}S(\frac{b}{d})h(b))d=1∑μ(d)(d∣a∑S(da)h(a))(d∣b∑S(db)h(b))
然后就好像没得化简了,先处理出F(d,n)=∑i=1nh(i×d)S(i)F(d,n)=\sum_{i=1}^nh(i\times d)S(i)F(d,n)=∑i=1nh(i×d)S(i)
发现ddd很大的时候后面那个东西的取值就很小,但是ddd很多,需要快速处理。
设定一个分界值TTT,每次小于TTT的部分我们就暴力用FFF数组计算,大于TTT的部分我们预处理出一个
G(d,i,j)=∑x=T+1dF(i)F(j)μ(d)G(d,i,j)=\sum_{x=T+1}^dF(i)F(j)\mu(d)G(d,i,j)=x=T+1∑dF(i)F(j)μ(d)
然后整除分块计算。
这里的kkk取N23N^{\frac{2}{3}}N32会平均一些,时间复杂度O(n43+Qn23)O(n^{\frac{4}{3}}+Qn^{\frac{2}{3}})O(n34+Qn32)
code
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#define ll long long
using namespace std;
const ll N=2e5+10,P=1<<30;
ll q,n,m,cnt,pri[N],mu[N],S[N],sg[N],g[N],o[N];
vector<int>f[N],d[N];
bool v[N];
void prime(){mu[1]=sg[1]=1;for(ll i=2;i<N;i++){if(!v[i])pri[++cnt]=i,mu[i]=-1,g[i]=2,sg[i]=2;for(ll j=1;j<=cnt&&i*pri[j]<N;j++){v[i*pri[j]]=1;if(i%pri[j]==0){g[i*pri[j]]=g[i]+1;sg[i*pri[j]]=sg[i]/g[i]*g[i*pri[j]];break;}mu[i*pri[j]]=-mu[i];g[i*pri[j]]=2;sg[i*pri[j]]=sg[i]*sg[pri[j]];}}for(ll i=1;i<N;i++)for(ll j=i;j<N;j+=i)(S[j]+=sg[j/i]*sg[j/i]*mu[i]%P)%=P;return;
}
signed main()
{freopen("math.in","r",stdin);freopen("math.out","w",stdout);prime();scanf("%lld",&q);ll lim=2e5;ll T=(ll)pow(lim,2.0/3.0)+1;f[0].resize(lim+1);for(ll i=1;i<=lim;i++){f[i].push_back(0); for(ll j=1;j<=lim/i;j++){ll tmp=f[i][j-1];f[i].push_back((tmp+S[i*j]*sg[j])%P);}}d[T].resize((lim/T)*(lim/T)+1);for(ll i=T+1;i<=lim;i++){ll p=lim/i;d[i].resize(p*p+1);for(ll j=1,sum=0;j<=lim/i;j++)for(ll k=j;k<=lim/i;k++)d[i][(j-1)*p+k]=(d[i-1][(j-1)*o[i-1]+k]+f[i][j]*f[i][k]*mu[i])%P;o[i]=p;}while(q--){scanf("%lld%lld",&n,&m);if(n>m)swap(n,m);ll ans=0;for(ll i=1;i<=min(T,n);i++)(ans+=1ll*f[i][n/i]*f[i][m/i]*mu[i]%P)%=P;for(ll l=T+1,r;l<=n;l=r+1){r=min(n/(n/l),m/(m/l));(ans+=d[r][(n/l-1)*o[r]+m/l]-d[l-1][(n/l-1)*o[l-1]+m/l])%=P;}printf("%lld\n",(ans+P)%P);}return 0;
}