题目链接:哆啦A梦传送门
题解:
f
(
n
,
a
,
b
)
=
∑
i
=
1
n
∑
j
=
1
i
g
c
d
(
i
a
−
j
a
,
i
b
−
j
b
)
[
g
c
d
(
i
,
j
)
=
=
1
]
f(n,a,b)=\sum_{i=1}^{n}\sum_{j=1}^{i}gcd(i^a-j^a,i^b-j^b)[gcd(i,j)==1]
f(n,a,b)=∑i=1n∑j=1igcd(ia−ja,ib−jb)[gcd(i,j)==1]
我们得知道有这个公式:
g
c
d
(
i
a
−
j
a
,
i
b
−
j
b
)
=
i
g
c
d
(
a
,
b
)
−
j
g
c
d
(
a
,
b
)
gcd(i^a-j^a,i^b-j^b)=i^{gcd(a,b)-j^{gcd(a,b)}}
gcd(ia−ja,ib−jb)=igcd(a,b)−jgcd(a,b)
故上式等价于:
题目说了a,b互质,故a,b就不用管它了
f
(
n
,
a
,
b
)
=
∑
i
=
1
n
∑
j
=
1
i
(
i
−
j
)
[
g
c
d
(
i
,
j
)
=
1
]
=
(
∑
i
=
1
n
∑
j
=
1
i
i
−
∑
i
=
1
n
∑
j
=
1
i
j
)
[
g
c
d
(
i
,
j
)
=
1
]
=
∑
i
=
1
n
i
∗
φ
(
i
)
−
∑
i
=
1
n
(
i
∗
φ
(
i
)
2
+
[
i
=
=
1
]
)
=
1
2
{
(
∑
i
=
1
n
i
∗
φ
(
i
)
)
−
1
)
}
\begin{aligned} f(n,a,b)&=\sum_{i=1}^{n}\sum_{j=1}^{i}(i-j)[gcd(i,j)=1]\\ &=(\sum_{i=1}^{n}\sum_{j=1}^{i}i-\sum_{i=1}^{n}\sum_{j=1}^{i}j)[gcd(i,j)=1]\\ &=\sum_{i=1}^{n}i*\varphi(i)-\sum_{i=1}^{n}(\frac{i*\varphi(i)}{2}+[i==1])\\ &=\frac{1}{2} \{(\sum_{i=1}^{n}i*\varphi(i))-1)\}\\ \end{aligned}
f(n,a,b)=i=1∑nj=1∑i(i−j)[gcd(i,j)=1]=(i=1∑nj=1∑ii−i=1∑nj=1∑ij)[gcd(i,j)=1]=i=1∑ni∗φ(i)−i=1∑n(2i∗φ(i)+[i==1])=21{(i=1∑ni∗φ(i))−1)}
减1是因为
g
c
d
(
1
,
1
)
=
1
gcd(1,1)=1
gcd(1,1)=1。
故我们就可以杜教筛了。
设
f
(
n
)
=
n
∗
φ
(
n
)
,
g
(
n
)
=
i
d
(
n
)
=
n
f(n)=n*\varphi(n),g(n)=id(n)=n
f(n)=n∗φ(n),g(n)=id(n)=n
由杜教筛的公式得:
S
(
n
)
=
∑
i
=
1
n
∑
d
∣
i
f
(
d
)
∗
g
(
i
d
)
−
∑
d
=
2
n
g
(
d
)
S
(
⌊
n
d
⌋
)
=
∑
i
=
1
n
∑
d
∣
i
φ
(
d
)
∗
i
−
∑
d
=
2
n
d
∗
S
(
⌊
n
d
⌋
)
=
∑
i
=
1
n
i
2
−
∑
d
=
2
n
d
∗
S
(
⌊
n
d
⌋
)
\begin{aligned}S(n)&=\sum_{i=1}^{n}\sum_{d|i}f(d)*g(\frac{i}{d})-\sum_{d=2}^{n}g(d)S(\left \lfloor \frac{n}{d} \right \rfloor)\\ &=\sum_{i=1}^{n}\sum_{d|i}\varphi(d)*i-\sum_{d=2}^{n}d*S(\left \lfloor \frac{n}{d} \right \rfloor)\\ &=\sum_{i=1}^{n}i^2-\sum_{d=2}^{n}d*S(\left \lfloor \frac{n}{d} \right \rfloor)\end{aligned}
S(n)=i=1∑nd∣i∑f(d)∗g(di)−d=2∑ng(d)S(⌊dn⌋)=i=1∑nd∣i∑φ(d)∗i−d=2∑nd∗S(⌊dn⌋)=i=1∑ni2−d=2∑nd∗S(⌊dn⌋)
上面是用杜教筛写的。
赛时我自己用莫比乌斯反演推了一个公式,不知是哪里错,有点迷,下次遇到自己推出以为正确的公式,但就是出不来正确结果,而自己也不知道是哪里出问题时,应该果断放弃这个公式,转而去想其它方法解决。
代码:
#include<bits/stdc++.h>
#include<tr1/unordered_map>
const int N=1e6+10;
using namespace std;
typedef long long LL;
const LL mod=1e9+7;
const LL inv2=500000004;
const LL inv6=166666668;
const LL inv24=41666667;
bool vis[N];
int phi[N];
LL sum1[N];
int tot,prime[N];
tr1::unordered_map<int,LL>w;
void get(int maxn)
{
tot=0;
phi[1]=1;
for(int i=2;i<=maxn;i++)
{
if(!vis[i])
{
prime[++tot]=i;///素数
phi[i]=i-1; ///欧拉函数
}
for(int j=1;j<=tot&&prime[j]*i<=maxn;j++)
{
vis[i*prime[j]]=1;
if(i%prime[j]==0)
{
phi[i*prime[j]]=phi[i]*prime[j];
break;
}
else phi[i*prime[j]]=phi[i]*(prime[j]-1);
}
}
sum1[0]=0;
for(int i=1;i<=maxn;i++){
sum1[i]=(sum1[i-1]+1LL*i*phi[i]%mod)%mod;
}
}
///前n项平方和
LL H(LL n)
{
n%=mod;
LL ans=n*(n+1)%mod*(2*n+1)%mod*inv6%mod;
return ans;
}
LL djs(int x)
{
if(x<=1000000)return sum1[x];
if(w[x])return w[x];
LL ans=H((LL)x);
for(int l=2,r;l<=x;l=r+1)
{
r=x/(x/l);
ans=(ans-(1LL*(r-l+1)*(l+r)/2)%mod*djs(x/l)%mod+mod)%mod;
}
return w[x]=ans;
}
int main()
{
int t,n;
get(1000000);
scanf("%d",&t);
while(t--)
{
int a,b;
scanf("%d%d%d",&n,&a,&b);
int r;
LL item=(djs(n)-1+mod)%mod;
item=item*inv2%mod;
printf("%lld\n",item);
}
return 0;
}
\begin{aligned}\end{aligned}