题意
给出n个x,求∑1≤a,b≤ngcd(xa−1,xb−1)∑1≤a,b≤ngcd(xa−1,xb−1)
1≤n,x≤1000001≤n,x≤100000,300组数据。
分析
有个结论就是gcd(xa−1,xb−1)=xgcd(a,b)−1gcd(xa−1,xb−1)=xgcd(a,b)−1
枚举d=gcd(a,b)d=gcd(a,b)后答案就等于
∑d=1n(xd−1)(2∑j=1⌊nd⌋φ(j)−1)∑d=1n(xd−1)(2∑j=1⌊nd⌋φ(j)−1)
直接大力分块即可。
代码
#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;
}