[egin{aligned}
ans&=sum_{i=a}^{b} ext{lcm}(i,b)\
&=sum_{i=a}^{b}frac{ib}{gcd(i,b)}\
&=sum_{d|b}frac{b}{d}sum_{i=a}^{b}i[gcd(i,b)=d]\
&=sum_{d|b}frac{b}{d}sum_{i=a/d}^{b/d}id[gcd(i,b/d)=1]\
&=bsum_{d|b}sum_{i=a/d}^{b/d}isum_{k|i,k|b/d}mu(k)\
&=bsum_{d|b}sum_{k|frac{b}{d}}mu(k)sum_{i=a/d,k|i}^{b/d}i\
&=bsum_{d|b}sum_{k|frac{b}{d}}mu(k)kfrac{(lceilfrac{a}{dk}
ceil+lfloorfrac{b}{dk}
floor) imes(-lceilfrac{a}{dk}
ceil+lfloorfrac{b}{dk}
floor+1)}{2}\
&=bsum_{T|b}frac{(lceilfrac{a}{T}
ceil+lfloorfrac{b}{T}
floor) imes(-lceilfrac{a}{T}
ceil+lfloorfrac{b}{T}
floor+1)}{2}sum_{dmid T}mu(d) imes d
end{aligned}
]
[egin{aligned}
sum_{dmid n}mu(d) imes d=prod (1-p_i)
end{aligned}
]
然后大力跑一下dfs即可。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll inf=1e9;
const int MAXN=200005;
const int MAX=100005;
const ll mod=1e9+7;
const ll inv2=mod-mod/2;
template <typename T>
void read(T &x) {
T flag=1;
char ch=getchar();
for (; '0'>ch||ch>'9'; ch=getchar()) if (ch=='-') flag=-1;
for (x=0; '0'<=ch&&ch<='9'; ch=getchar()) x=x*10+ch-'0';
x*=flag;
}
int T;
ll A, B;
int prime[MAX+5], cnt;
int p[MAXN], tot, c[MAXN];
bool mark[MAX+5];
ll ans;
void get_prime() {
for (int i=2; i<=MAX; i++) {
if (!mark[i]) {
prime[++cnt]=i;
}
for (int j=1; j<=cnt&&prime[j]*i<=MAX; j++) {
mark[prime[j]*i]=true;
if (i%prime[j]==0) break;
}
}
}
void dfs(int cur, ll now, ll fuck_ccf) {
if (cur>tot) {
ans+=1ll*((A+now-1)/now+B/now)*(B/now-(A+now-1)/now+1)%mod*inv2%mod*fuck_ccf%mod;
ans%=mod;
return;
}
dfs(cur+1, now, fuck_ccf);
int tmp=now;
for (int i=1; i<=c[cur]; i++) {
tmp*=p[cur];
dfs(cur+1, tmp, fuck_ccf*(1-p[cur]+mod)%mod);
}
}
void solve() {
ans=0;
tot=0;
int x=B;
for (int i=1; 1ll*prime[i]*prime[i]<=x&&i<=cnt; i++) {
if (x%prime[i]==0) {
p[++tot]=prime[i];
c[tot]=0;
while (x%prime[i]==0) {
c[tot]++;
x/=prime[i];
}
}
}
if (x>1) {
p[++tot]=x;
c[tot]=1;
}
dfs(1, 1, 1);
printf("%lld
", ans*B%mod);
}
int main() {
get_prime();
read(T);
while (T--) {
read(A); read(B);
solve();
}
return 0;
}