III.DZY Loves Math
题意:求
\(\sum\limits_{i=1}^n\sum\limits_{j=1}^mf(\gcd(i,j))\),其中\(f(x)\)表示\(x\)的所有质因数中次数最高的一个的次数。
近乎套路的一堆操作后,我们得到了
\(\sum\limits_{i=1}^{\min(n,m)}\left\lfloor\dfrac{n}{i}\right\rfloor\left\lfloor\dfrac{m}{i}\right\rfloor(f*\mu)(i)\)
但是,稍微想想就发现,\(f\)函数并不是积性函数。例如,\(f(5)=1,f(6)=1,\gcd(5,6)=1,f(5*6)=f(30)=1\)。
那怎么办呢?
考虑\((f*\mu)(x)=\sum\limits_{d|x}\mu(d)f(\dfrac{x}{d})\)。
我们设\(x=\prod_{i=1}^k(P_i)^{a_i}\)。
显然,只有当\(d=\prod_{i=1}^k(P_i)^{b_i},b_i\in\{0,1\}\)时,才有\(\mu(d)\neq 0\)。
我们设某个具有\(\min(a_i)\)的\(P_i\)为\(p\)。
再设一个\(d|x\)但\(\gcd(d,p)=1\)的\(d\)。
则,\(\mu(d)=-\mu(dp),f(\dfrac{x}{d})=f(\dfrac{x}{dp})\)
则\(\mu(d)f(\dfrac{x}{d})+\mu(dp)f(\dfrac{x}{dp})=0\)
因此,大部分情况下,\((f*\mu)(x)=0\)
唯一的特例就是所有的\(a_i\)全部相等时。这时,就算是\(\min(a_i)\)也会对\(f\)有影响。
当然,除了\(d=1\)和\(d=\prod_{i=1}^k(P_i)\)两个值以外,其他的\(\mu(d)f(\dfrac{x}{d})\)还是会互相抵消掉。
当\(d=1\)时,\(\mu(d)f(\dfrac{x}{d})=a_i\);当\(d=\prod_{i=1}^k(P_i)\)时,\(\mu(d)f(\dfrac{x}{d})=(a_i-1)*\mu(d)\)
这两个求和的话,我们最终得到了\(-\mu(d)\)。
我们设\(f*\mu=g\)。然后就只要枚举每个\(\mu(x)\neq 0\)的\(x\),将它的所有次方的\(g\)设为\(-\mu(x)\)即可。这个复杂度为\(O(n)\),因为每一个\(g(x)\)只会被访问一次。
虽然这是莫反题,但本题最大的难点是线性时间内求出\(f*\mu\)的值。数学素养是很重要的。(就像我,根本求不出来\(f*\mu\)到底是个什么东西)
代码:
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=1e7;
int n,m,pri[N+5],mu[N+5],g[N+5],T,res;
void init(){
mu[1]=1;
for(int i=2;i<=N;i++){
if(!pri[i])pri[++pri[0]]=i,mu[i]=-1;
for(int j=1;j<=pri[0]&&i*pri[j]<=N;j++){
pri[i*pri[j]]=true;
if(!(i%pri[j]))break;
mu[i*pri[j]]=-mu[i];
}
}
for(int i=2;i<=N;i++)if(mu[i])for(int j=i;j<=N;j*=i)g[j]=-mu[i];
for(int i=1;i<=N;i++)g[i]+=g[i-1];
}
signed main(){
scanf("%lld",&T),init();
while(T--){
scanf("%lld%lld",&n,&m),res=0;
for(int l=1,r;l<=min(n,m);l=r+1)r=min(n/(n/l),m/(m/l)),res+=(g[r]-g[l-1])*(n/l)*(m/l);
printf("%lld\n",res);
}
return 0;
}