Spring-07-AOP
積性函式指對於所有互質的整數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\)
元函式: \(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}\)
莫比烏斯反演
若
\[g(n)=\sum_{d \mid n} f(d) \]
則
\[f(n)=\sum_{d |n} \mu(d) g\left(\frac{n}{d}\right) \]
證明:這裡需要用到前面提到的性質: \(\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);
}
}