gcd
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 732 Accepted Submission(s): 254
Problem Description
Little White learned the greatest common divisor, so she plan to solve a problem: given x, n,
query ∑gcd(-1,−1) (1≤a,b≤n)
Input
The first line of input is an integer T ( 1≤T≤300)
For each test case ,the single line contains two integers x and n ( 1≤x,n≤1000000)
Output
For each testcase, output a line, the answer mod 1000000007
Sample Input
5
3 1
4 2
8 7
10 5
10 8
Sample Output
2
24
2398375
111465
111134466
Source
题意:
a的取值范围是[1,n],b的取值范围是[1,n],求 之和
分析:
首先, ,问题转化为求1到n,最大公约数为d的个数 * (x^d)-1的和
ans=∑s[d]∗(x^d−1),记s[d]=最大公约数为d的个数,也就是1到n/d以内,互质的对数,显然是欧拉函数的前缀和
s[d]=2*(phi[1]+phi[2]+...+phi[n/d])-1
注意到:d不同,但是n/d一样,也就是s[d]可能有多个相同,比如 10/6 10/7 10/8 10/9 10/10,所以求s[d]相同的项,我们可以用等比公式求和(快速幂+逆元 ),直接进行除法会发生精度误差,所以考虑求逆元
所以我们只要找到每一段s[d]就可以 即 r=n/(n/d),r为最后一个相同s[d]的下标,d为第一个s[d]相同的下标
由于第一个下标为d,最后一个下标为r,n=(r-d+1)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e6+7;
#define mod 1000000007
ll phi[maxn];
void get_phi()
{
for(int i=1;i<maxn;i++)
phi[i]=i;
for(int i=2;i<maxn;i++)
if(phi[i]==i)
for(int j=i;j<maxn;j+=i)
phi[j]=phi[j]/i*(i-1);
for(int i=3;i<maxn;i++)
phi[i]=(phi[i]+phi[i-1])%mod;
for(int i=2;i<maxn;i++)
phi[i]=(2*phi[i]+1)%mod;
}
ll quickPow(ll a,ll b)
{
ll res=1;
while(b){
if(b&1) res=(res*a)%mod;
a=a*a%mod;
b>>=1;
}
return res;
}
int main()
{
get_phi();
int T;
scanf("%d",&T);
while(T--){
ll x,n;
scanf("%lld%lld",&x,&n);
if(x==1)
{
printf("0\n");
continue;
}
ll ans=0;
ll inv=quickPow(x-1,mod-2);//费马小定理求逆元
for(int i=1;i<=n;i=n/(n/i)+1)
{
ll r=n/(n/i);//闭区间终点,i为闭区间起点
ll part=((quickPow(x,i)*(quickPow(x,r-i+1)-1)%mod)*inv%mod-(r-i+1)+mod)%mod;//等比数列求和
ans=(ans+(phi[n/i]*part)%mod+mod)%mod;
}
printf("%lld\n",(ans+mod)%mod);
}
return 0;
}