积性函数
积性函数指对于所有互质的整数a和b有性质f(ab)=f(a)f(b)的数论函数。
狄利克雷卷积
\((f * g)(n)=\sum_{d \mid n} f(d) g\left(\frac{n}{d}\right)\)
性质1:
两个积性函数的狄利克雷卷积还是积性函数。
证明:感性理解一下,两个互质的下标乘起来,相当于两个和式乘起来,因为是互质的相当于枚举到了乘积的所有约数,因为和式里面都是积性函数所以乘起来也是积性函数。
性质2:
三大运算规律:结合律,交换律,分配律。
常见运算
除数函数: \(\sigma_{x}(n)=\sum_{d \mid n} d^{x}\)
约数个数函数: \(d(n)=\sum_{d \mid n} 1\) 约数和函数: \(\sigma(n)=\sum_{d n} d\)
元函数: \(e(n)=[n=1](\{1,0,0,0,0 \ldots . . .\})\)
恒等函数: \(I(n)=1(\{1,1,1,1,1 \ldots \ldots\})\)
单位函数: \(\varepsilon(n)=n(\{1,2,3,4,5 \ldots \ldots\})\)
欧拉函数: \(\phi(n)\) 莫比乌斯函数: \(\mu(n)\)
\(\mu(i)=\left\{\begin{array}{c}1, i=1 \\ (-1)^{k}, i=p 1 * p 2 * \ldots * p k \\ 0, \text { rest }\end{array}\right.\)
\(\varepsilon=\phi * I \Leftrightarrow n=\sum_{d \mid n} \phi(d)\)
\(d=I * I \Leftrightarrow d(n)=\sum_{d \mid n} 1\)
\(\sigma=\varepsilon * I \Leftrightarrow \sigma(n)=\sum_{d \mid n} d\)
\(e=I * \mu \Leftrightarrow[n==1]=\sum_{d \mid n} \mu(d)\)
\(\phi=\varepsilon * \mu \Leftrightarrow \phi(n) \sum_{d \mid n} \mu(d) * \frac{n}{d}\)
莫比乌斯反演
若
则
证明:这里需要用到前面提到的性质: \(\mu * I=\epsilon\)
给出的条件等价于 \(g=f * I\)
所以 \(g * \mu=f * I * \mu=f * \epsilon=f\) 即 \(g * \mu=f\) 即 结论
杜教筛
\(g(1) S(n)=\sum_{i=1}^{n}(f * g)(i)-\sum_{i=2}^{n} g(i) S\left(\left\lfloor\frac{n}{i}\right\rfloor\right)\)
求解\(S(n)\),可以设定\(f\)和\(g\)。
\((1)\mu(n)\)前缀和
考虑到莫比乌斯函数的性质 \(\mu * I=\epsilon,\) 自然想到取 \(f=\mu, g=I, f * g=\epsilon\)
\((2)\varphi\) 的前缀和
考虑到 \(\varphi\) 的性质 \(\varphi * I=i d,\) 取 \(f=\varphi, g=I, f * g=i d\)
(3)\(\sum_{i=1}^{n} \varphi(i) \cdot i\)
令 \(f=\varphi \cdot i d, g=i d,\) 考虑迪利克雷卷积的形式得到 \((f * g)(n)=\sum_{d \mid n}(\varphi(d) \cdot d) \cdot\left(\frac{n}{d}\right)=\)
\(n \sum_{d \mid n} \varphi(d)=n^{2}\)
即 \((f * g)(i)=i^{2}\)
这样就可以快速求得 \((f * g)(i)\) 的前缀和 \(\frac{n(n+1)(2 n+1)}{6}\)
const int N=1000009;
const int mod=1e9+7;
int pre[N];
int phi[N];
int vis[N];
int prime[N];
int _2,_6;
unordered_map<int,int>mp;
void init()
{
phi[1]=1;
int cnt=0;
for(int i=2;i<=N;i++)
{
if(!vis[i])
{
prime[++cnt]=i;
phi[i]=i-1;
}
for(int j=1;j<=cnt&&prime[j]*i<=N;j++)
{
vis[prime[j]*i]=1;
if(i%prime[j]==0)
{
phi[i*prime[j]]=phi[i]*prime[j];
break;
}
phi[i*prime[j]]=phi[i]*phi[prime[j]];
}
}
}
int getsum(int n)
{
if(n<=N)return pre[n];
if(mp.count(n))return mp[n];
int res=n*(n+1)%mod*(2*n+1)%mod*_6%mod;
for(int l=2,r;l<=n;l=r+1)
{
r=n/(n/l);
res-=(l+r)*(r-l+1)/2%mod*getsum(n/l)%mod;
}
return mp[n]=res%mod;
}
int qpow(int a,int b,int mod)
{
if(b==0)return 1;
if(b%2==0)
{
int temp=qpow(a,b/2,mod)%mod;
return temp*temp%mod;
}
else
{
return qpow(a,b-1,mod)*a%mod;
}
}
main(void)
{
init();
for(int i=1;i<=N;i++)
{
pre[i]=(pre[i-1]+i*phi[i])%mod;
}
int t=read();
_2=qpow(2,mod-2,mod);//2乘法逆元
_6=qpow(6,mod-2,mod);//6乘法逆元
while(t--)
{
int n=read();
int a=read();
int b=read();
printf("%lld\n",(getsum(n)-1+mod)%mod*_2%mod);
}
}