题意
给出n个x,求
∑1≤a,b≤ngcd(xa−1,xb−1)
∑
1
≤
a
,
b
≤
n
g
c
d
(
x
a
−
1
,
x
b
−
1
)
1≤n,x≤100000
1
≤
n
,
x
≤
100000
,300组数据。
分析
有个结论就是
gcd(xa−1,xb−1)=xgcd(a,b)−1
g
c
d
(
x
a
−
1
,
x
b
−
1
)
=
x
g
c
d
(
a
,
b
)
−
1
枚举
d=gcd(a,b)
d
=
g
c
d
(
a
,
b
)
后答案就等于
直接大力分块即可。
代码
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long LL;
const int N=1000005;
const int MOD=1000000007;
int tot,prime[N],phi[N];
bool not_prime[N];
int ksm(int x,int y)
{
int ans=1;
while (y)
{
if (y&1) ans=(LL)ans*x%MOD;
x=(LL)x*x%MOD;y>>=1;
}
return ans;
}
void get_prime(int n)
{
phi[1]=1;
for (int i=2;i<=n;i++)
{
if (!not_prime[i]) prime[++tot]=i,phi[i]=i-1;
for (int j=1;j<=tot&&i*prime[j]<=n;j++)
{
not_prime[i*prime[j]]=1;
if (i%prime[j]==0)
{
phi[i*prime[j]]=phi[i]*prime[j];
break;
}
phi[i*prime[j]]=phi[i]*phi[prime[j]];
}
}
for (int i=2;i<=n;i++) (phi[i]+=phi[i-1])%=MOD;
}
int get(int x,int l,int r)
{
if (x==1) return r-l+1;
return (LL)(ksm(x,r+1)+MOD-ksm(x,l))*ksm(x-1,MOD-2)%MOD;
}
int main()
{
get_prime(1000000);
int T;scanf("%d",&T);
while (T--)
{
int x,n;scanf("%d%d",&x,&n);
int ans=MOD-(LL)n*n%MOD;
for (int i=1,last;i<=n;i=last+1)
{
last=n/(n/i);
(ans+=(LL)(phi[n/i]*2-1)*get(x,i,last)%MOD)%=MOD;
}
printf("%d\n",ans);
}
return 0;
}