多次询问,求
题解写不动了……~~自己~~搞出来的和大佬们的都一样,就贴一发[大佬的博客](https://www.cnblogs.com/GXZlegend/p/7000042.html)吧。
如果不会的话,可以先做这个弱化版的:[单次询问](https://www.luogu.org/problemnew/show/P1829) 也附上一篇[大佬的博客](https://www.luogu.org/blog/peng-ym/solution-p1829)
这里有几个枚举的小技巧,比如其中有一项 $$sum _ {x = 1} ^ {n} sum_ {i = 1} ^ {lfloor frac{n}{d} floor} sum_ {j = 1} ^ {lfloor frac{m}{d} floor} i j sum _ {x | gcd(i, j)} mu(x)$$ 我们发现$x | gcd(i, j)$这个条件很不爽,于是可以换一个思路:把枚举$i,j$变成枚举$ax, bx$。 嗯就这样…… ```c++ #include
int prm[maxn], v[maxn];
ll f[maxn], sum[maxn];
void init()
{
f[1] = 1;
for(int i = 2; i < maxn; ++i)
{
if(!v[i]) v[i] = i, prm[++prm[0]] = i, f[i] = ((i - (ll)i * i) % mod + mod) % mod;
for(int j = 1; i * prm[j] < maxn && j <= prm[0]; ++j)
{
v[i * prm[j]] = prm[j];
if(i % prm[j] == 0)
{
f[i * prm[j]] = f[i] * prm[j] % mod;
break;
}
f[i * prm[j]] = f[i] * f[prm[j]] % mod;
}
}
for(int i = 1; i < maxn; ++i) sum[i] = (sum[i - 1] + f[i]) % mod;
}
ll s(ll n)
{
return n * (n + 1) / 2 % mod;
}
ll solve(ll n, ll m)
{
ll ret = 0;
int Min = min(n, m);
for(int l = 1, r; l <= Min; l = r + 1)
{
r = min(n / (n / l), m / (m / l));
ret = (ret + s(n / l) * s(m / l) % mod * (sum[r] - sum[l - 1] + mod) % mod) % mod;
}
return ret;
}
int main()
{
init();
int T = read();
while(T--)
{
int n = read(), m = read();
write(solve(n, m)), enter;
}
return 0;
}