题目大意:
给出2个数a, b,求LCM(a,b) + LCM(a+1,b) + .. + LCM(b,b)。
1<=a<=b<=10^9
T组数据,1<=T<=50000
且数据为随机,没有构造的卡人数据。
题解:
这一题我是不会的,去网上看了下题解,发现了一个奇怪的反演姿势。
必要结论:
∑d|nμ(d)=(n=1)
证明略。
Ans=∑bi=alcm(i)
=b∗∑d|b∑⌈ad⌉i=⌊bd⌋i∗(gcd(i,bd)=1)
=b∗∑d|b∑⌈ad⌉i=⌊bd⌋i∗∑d′|gcd(i,bd)μ(d′)
=b∗∑d|b∑d′|bdμ(d′)∗d′∗∑⌈ad⌉i=⌊bd⌋i∗(d′|gcd(i,bd))
=b∗∑d|b∑d′|bdμ(d′)∗d′∗∑⌈ad∗d′⌉i=⌊bd∗d′⌋i
=b∗∑d|b∑d′|bdμ(d′)∗d′∗(⌊bd∗d′⌋−⌈ad∗d′⌉+1)∗(⌊bd∗d′⌋+⌈ad∗d′⌉)/2
设T = d * d’
=b∗∑T|b(⌊bT⌋−⌈aT⌉+1)∗(⌊bT⌋+⌈aT⌉)/2∗∑d|Tμ(d)∗d
我们观察一下
∑d|Tμ(d)∗d
狄利克雷卷积做了这么多,轻松可得:
若
T=∏pqii
,那么
∑d|Tμ(d)∗d=∏1−pi
在递归枚举约数的时候维护一下即可。
Code:
#include<stdio.h>
#define ll long long
#define fo(i, x, y) for(int i = x; i <= y; i ++)
using namespace std;
const ll mo = 1e9 + 7, ni_2 = 5e8 + 4;
const int Maxn = 32000;
bool bz[Maxn + 1];
int T, a, b, z, i, u[35], v[35], p[3500];
ll ans;
void dg(int x, int d, ll s) {
if(x > u[0]) {
ll t1 = b / d, t2 = (a + d - 1) / d ;
ans += (t1 + t2) * (t1 - t2 + 1) * s;
return;
}
dg(x + 1, d, s);
s = s * (1 - u[x]);
fo(i, 1, v[x]) d *= u[x], dg(x + 1, d, s);
}
int main() {
for(i = 2; i <= Maxn; i ++) {
if(!bz[i]) p[++ p[0]] = i;
fo(j, 1, p[0]) {
int k = i * p[j]; if(k > Maxn) break;
bz[k] = 1; if(i % p[j] == 0) break;
}
}
for(scanf("%d", &T); T; T --) {
scanf("%d %d", &a, &b);
z = b; u[0] = 0;
for(i = 1; p[i] * p[i] <= z; i ++) {
if(z % p[i]) continue;
u[++ u[0]] = p[i]; v[u[0]] = 0;
while(z % p[i] == 0) v[u[0]] ++, z /= p[i];
}
if(z > 1) u[++ u[0]] = z, v[u[0]] = 1;
ans = 0;
dg(1, 1, 1);
printf("%lld\n", (ans % mo + mo) % mo * ni_2 % mo * b % mo);
}
}