大致题意:告诉你n、a和b,让你求
中间那个gcd(i^a-j^a,i^b-j^b)这个看起来很吓人,其实你打表会发现其实它等于i-j,那么就变成了求
这个显然可以拆成两个部分
第一部分就是phi(i)的和,第二部分就是所有与i互质的小于i的数字的和,即
利用杜教筛尝试求i*phi(i)的前缀和,我们令f(i)=i*phi(i),有
然后考虑开始求和
套上杜教筛即可,具体见代码:
#include<bits/stdc++.h>
#define N 3333310
#define INF 0x3f3f3f3f
#define eps 1e-6
#define pi 3.141592653589793
#define mod 1000000007
#define P 1000000007
#define LL long long
#define pb push_back
#define fi first
#define se second
#define cl clear
#define si size
#define lb lower_bound
#define ub upper_bound
#define bug(x) cerr<<#x<<" : "<<x<<endl
#define mem(x) memset(x,0,sizeof x)
#define sc(x) scanf("%d",&x)
#define scc(x,y) scanf("%d%d",&x,&y)
#define sccc(x,y,z) scanf("%lld%lld%lld",&x,&y,&z)
using namespace std;
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/hash_policy.hpp>
#include <ext/pb_ds/priority_queue.hpp>
using namespace __gnu_pbds;
unordered_map<LL,LL> mp;
const LL inv2=500000004;
const LL inv6=166666668;
int p[N],cnt,phi[N],psum[N],isp[N];
int vis[N];
void init()
{
int sz=0;
phi[1]=1;
for(int i=2;i<N;i++)
{
if(!isp[i])p[++sz]=i,phi[i]=i-1;
for(int j=1;j<=sz&&(LL)i*p[j]<N;j++)
{
isp[i*p[j]]=1;
if(i%p[j]==0)
{
phi[p[j]*i]=phi[i]*p[j];
break;
} else phi[p[j]*i]=(p[j]-1)*phi[i];
}
}
for(int i=1;i<N;i++)
psum[i]=(psum[i-1]+(LL)i*phi[i]%mod)%mod;
}
LL S(LL x) {
if(mp[x]) return mp[x];
if(x<N) return psum[x];
LL ans=0,res=((x*(x+1)%mod)*((2*x+1)%mod))%mod;
res=res*inv6%mod;
for(LL l=2,r;l<=x;l=r+1) {
LL tmp=x/l; r=x/tmp;
ans=(ans+((r+l)%mod*(r-l+1+mod)%mod*inv2%mod)*S(tmp)%mod)%mod;
}
return mp[x]=(res-ans+mod)%mod;
}
int main() {
init();
int T;
for(sc(T);T;T--){
LL n,a,b,ans;
sccc(n,a,b);
ans=(S(n)-1+mod)%mod;
ans=ans*inv2%mod;
printf("%lld\n",ans%mod);
}
return 0;
}