huntian oy (数论&卷积&杜教筛)
思路:
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 ] ( m o d 1 0 9 + 7 ) f(n,a,b)=\sum\limits_{i=1}^n \sum\limits_{j=1}^i gcd(i^a-j^a,i^b-j^b)[gcd(i,j)=1]\pmod{10^9+7} f(n,a,b)=i=1∑nj=1∑igcd(ia−ja,ib−jb)[gcd(i,j)=1](mod109+7)
g c d ( i a − j a , i b − j b ) gcd(i^a-j^a,i^b-j^b) gcd(ia−ja,ib−jb)
i a − j a = ( i − j ) ( i a − 1 + i a − 2 j + ⋯ + j a − 1 ) i^a-j^a=(i-j)(i^{a-1}+i^{a-2}j+\dots+j^{a-1}) ia−ja=(i−j)(ia−1+ia−2j+⋯+ja−1)
i b − j b = ( i − j ) ( i b − 1 + i b − 2 j + ⋯ + j b − 1 ) i^b-j^b=(i-j)(i^{b-1}+i^{b-2}j+\dots+j^{b-1}) ib−jb=(i−j)(ib−1+ib−2j+⋯+jb−1)
因为 a , b a,b a,b互质。
所以 g c d ( i a − j a , i b − j b ) = i − j gcd(i^a-j^a,i^b-j^b)=i-j gcd(ia−ja,ib−jb)=i−j
原式 = ∑ i = 1 n ∑ j = 1 i ( i − j ) [ g c d ( i , j ) = 1 ] = ∑ i = 1 n 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 − 1 2 ) = ∑ i = 1 n i × φ ( i ) − 1 2 =\sum\limits_{i=1}^n \sum\limits_{j=1}^i (i-j)[gcd(i,j)=1]\\=\sum\limits_{i=1}^n i\times \varphi(i)-\sum\limits_{i=1}^n \sum\limits_{j=1}^i j[gcd(i,j)=1]\\=\sum\limits_{i=1}^n i\times \varphi(i)-(\sum\limits_{i=1}^n \dfrac{i\times \varphi(i)}{2}-\dfrac{1}{2})\\=\dfrac{\sum\limits_{i=1}^n i\times \varphi(i)-1}{2} =i=1∑nj=1∑i(i−j)[gcd(i,j)=1]=i=1∑ni×φ(i)−i=1∑nj=1∑ij[gcd(i,j)=1]=i=1∑ni×φ(i)−(i=1∑n2i×φ(i)−21)=2i=1∑ni×φ(i)−1
然后一股神秘的卷积力量可将式子变为递推式。(这里卷积学的不好待补)
S ( n ) = ∑ i = 1 n i 2 − ∑ i = 2 n i S ( n i ) S(n)=\sum\limits_{i=1}^n i^2-\sum\limits_{i=2}^n iS(\dfrac{n}{i}) S(n)=i=1∑ni2−i=2∑niS(in)
对于 n ≤ 1 0 6 n\le 10^6 n≤106的数据可用第一个式子。
否则用递推式记忆化递归。
求 φ ( i ) \varphi(i) φ(i) 用欧拉筛即可。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=5e6+5,M=2e4+5,inf=0x3f3f3f3f,mod=1e9+7;
#define mst(a,b) memset(a,b,sizeof a)
#define lx x<<1
#define rx x<<1|1
#define reg register
#define PII pair<int,int>
#define fi first
#define se second
#define pb push_back
#define il inline
ll inv2,inv6,phi[N];
ll ksm(ll a,ll n){
ll ans=1;
while(n){
if(n&1) ans=ans*a%mod;
a=a*a%mod;
n>>=1;
}
return ans;
}
int a[N],p[N],cnt;
void Euler(int n){
phi[1]=1;
for(int i=2;i<=n;i++){
if(!a[i]){
p[++cnt]=i;
phi[i]=i-1;
}
for(int j=1;j<=cnt&&p[j]*i<=n;j++){
a[p[j]*i]=1;
if(i%p[j]==0){
phi[p[j]*i]=phi[i]*p[j];
break;
}
else phi[p[j]*i]=phi[i]*phi[p[j]];
}
}
for(int i=2;i<=n;i++){
phi[i]=(phi[i-1]+phi[i]*i%mod)%mod;
}
}
unordered_map<int,int>mp;
int solve(int n){
if(n<=N-5) return phi[n];
if(mp[n]) return mp[n];
ll tmp=1LL*n*(n+1)%mod*(2*n+1)%mod*inv6%mod; //这里要用3个mod
for(int l=2,r;l<=n;l=r+1){
r=n/(n/l);
tmp-=1LL*(r-l+1)*(l+r)/2%mod*solve(n/l)%mod;
tmp=(tmp%mod+mod)%mod;
}
return mp[n]=tmp;
}
int main(){
inv2=ksm(2,mod-2),inv6=ksm(6,mod-2);
int t;
Euler(N-5);
scanf("%d",&t);
while(t--){
int n,a,b;
scanf("%d%d%d",&n,&a,&b);
int ans=1LL*(solve(n)-1)*inv2%mod;
ans=(ans%mod+mod)%mod;
printf("%d\n",ans);
}
return 0;
}