Description:
求∑gcd(xa−1,xb−1)∑gcd(xa−1,xb−1)
Solution:
结论:∑gcd(xa−1,xb−1)=∑xgcd(a,b)−1∑gcd(xa−1,xb−1)=∑xgcd(a,b)−1
那么枚举gcdgcd,得出式子
∑nd=1(xd−1)∗(2∗∑ndi=1ϕi−1)∑d=1n(xd−1)∗(2∗∑i=1ndϕi−1)
前面等比数列求和,后面分块即可。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e6 + 5, P = 1e9 + 7;
int p[N], mark[N];
ll phi[N];
ll power(ll x, ll t) {
ll ret = 1;
for(; t; t >>= 1, x = x * x % P) {
if(t & 1) {
ret = ret * x % P;
}
}
return ret;
}
void sieve() {
phi[1] = 1;
for(int i = 2; i < N; ++i) {
if(!mark[i]) {
p[++p[0]] = i;
phi[i] = i - 1;
}
for(int j = 1; j <= p[0] && i * p[j] < N; ++j) {
mark[i * p[j]] = 1;
if(i % p[j] == 0) {
phi[i * p[j]] = phi[i] * p[j];
break;
}
phi[i * p[j]] = phi[i] * phi[p[j]];
}
}
for(int i = 2; i < N; ++i) {
phi[i] = (phi[i] + phi[i - 1]) % P;
}
}
ll get_s(ll n, ll q) {
if(!n) {
return 0;
}
if(q == 1) {
return n * q % P;
}
ll ret = q * (power(q, n) - 1 + P) % P * power(q - 1, P - 2) % P;
return ret;
}
int main() {
sieve();
int T;
scanf("%d", &T);
while(T--) {
int x, n;
scanf("%d%d", &x, &n);
ll ans = 0;
for(int i = 1, j = 0; i <= n; i = j + 1) {
j = n / (n / i);
ans = (ans + ((get_s(j, x) - get_s(i - 1, x) - (j - i + 1)) % P + P) % P * ((2 * phi[n / i] - 1) % P + P) % P) % P;
}
printf("%lld\n", ans);
}
return 0;
}