链接
题解
推一推式子,发现 ( i a − j a , i b − j b ) = ( i b − j b , i a − b − j a − b ) (i^a-j^a,i^b-j^b)=(i^b-j^b,i^{a-b}-j^{a-b}) (ia−ja,ib−jb)=(ib−jb,ia−b−ja−b)
这都证出来了,那不就结束了吗?
显然 ( i a − j a , i b − j b ) = i ( a , b ) − j ( a , b ) (i^a-j^a,i^b-j^b)=i^{(a,b)}-j^{(a,b)} (ia−ja,ib−jb)=i(a,b)−j(a,b)
题目在很不起眼的地方写了 a a a和 b b b互质,所以 ( a , b ) = 1 (a,b)=1 (a,b)=1
所以这题就是求
∑
i
=
1
n
∑
j
=
1
i
(
i
−
j
)
[
(
i
,
j
)
=
1
]
\sum_{i=1}^n\sum_{j=1}^i(i-j)[(i,j)=1]
i=1∑nj=1∑i(i−j)[(i,j)=1]
推一推就可以得到
1
2
∑
i
=
2
n
i
φ
(
i
)
\frac{1}{2}\sum_{i=2}^n i\varphi(i)
21i=2∑niφ(i)
杜教筛裸题
代码
#include <bits/stdc++.h>
#define maxn 1000010
#define linf (1ll<<60)
#define iinf 0x3f3f3f3f
#define mod 1000000007ll
#define cl(x) memset(x,0,sizeof(x))
#define rep(_,__) for(_=1;_<=(__);_++)
using namespace std;
typedef long long ll;
typedef pair<ll,ll> pll;
struct EasyMath
{
ll prime[maxn], phi[maxn];
bool mark[maxn];
ll fastpow(ll a, ll b, ll c)
{
ll t(a%c), ans(1ll);
for(;b;b>>=1,t=t*t%c)if(b&1)ans=ans*t%c;
return ans;
}
void get_prime(ll N)
{
ll i, j;
for(i=2;i<=N;i++)mark[i]=false;
*prime=0;
phi[1]=1;
for(i=2;i<=N;i++)
{
if(!mark[i])prime[++*prime]=i, phi[i]=i-1;
for(j=1;j<=*prime and i*prime[j]<=N;j++)
{
mark[i*prime[j]]=true;
if(i%prime[j]==0)
{
phi[i*prime[j]]=phi[i]*prime[j];
break;
}
phi[i*prime[j]]=phi[i]*(prime[j]-1);
}
}
}
}em;
ll f[1500], iphi[maxn], N, _6;
ll getf(ll x){return x<maxn?iphi[x]:f[N/x];}
ll S1(ll n)
{
return (n*(n+1)>>1)%mod;
}
void calc(ll n)
{
if(n<maxn or f[N/n])return;
ll &s=f[N/n], k, last;
s=n*(n+1)%mod*(2*n+1)%mod*_6%mod;
for(k=2;k<=n;k=last+1)
{
last=n/(n/k);
calc(n/k);
(s-=getf(n/k)*(S1(last)-S1(k-1)))%=mod;
}
}
int main()
{
ll i, T, a, b;
_6=em.fastpow(6,mod-2,mod);
cin>>T;
em.get_prime(maxn-1);
for(i=1;i<maxn;i++)iphi[i]=em.phi[i]*i%mod;
for(i=1;i<maxn;i++)(iphi[i]+=iphi[i-1])%=mod;
while(T--)
{
cin>>N>>a>>b;
cl(f);
calc(N);
ll ans=(getf(N)-1)*em.fastpow(2,mod-2,mod)%mod;
cout<<(ans+mod)%mod<<endl;
}
return 0;
}