Luogu 4240:毒瘤之神的考验

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/oi_Konnyaku/article/details/85231786

传送门

Sol

分开考虑 φ ( i j ) \varphi(ij) i j ij 的质因子
那么
φ ( i j ) = φ ( i ) φ ( j ) g c d ( i , j ) φ ( g c d ( i , j ) ) \varphi(ij)=\frac{\varphi(i)\varphi(j)gcd(i,j)}{\varphi(gcd(i,j))}
直接莫比乌斯反演
g ( x , i ) = j = 1 x φ ( i j ) g(x,i)=\sum_{j=1}^{x}\varphi(ij)
那么
a n s = i = 1 m i n ( n , m ) g ( n i , i ) g ( m i , i ) d i μ ( i d ) d φ ( d ) ans=\sum_{i=1}^{min(n,m)}g(\lfloor\frac{n}{i}\rfloor,i)g(\lfloor\frac{m}{i}\rfloor,i)\sum_{d|i}\mu(\frac{i}{d})\frac{d}{\varphi(d)}
后面的卷积可以直接筛
Θ ( T n ) \Theta(Tn) 当然不行了

f ( i ) = d i μ ( i d ) d φ ( d ) f(i)=\sum_{d|i}\mu(\frac{i}{d})\frac{d}{\varphi(d)}
s ( i , j , k ) s(i,j,k) 表示 p = 1 k g ( i , p ) g ( j , p ) f ( p ) \sum_{p=1}^{k}g(i,p)g(j,p)f(p)
考虑到当 i n i\le \sqrt{n} 的时候 s ( i , j , k ) s(i,j,k) 中的 i , j n i,j \ge \sqrt{n}
i n i\ge \sqrt{n} 的时候 s ( i , j , k ) s(i,j,k) 中的 i , j n i,j \le \sqrt{n}
所以可以预处理到 s ( 80 , 80 , k ) s(80,80,k) 对于小于 n / 80 n/80 的直接暴力

# include <bits/stdc++.h>
using namespace std;
typedef long long ll;

const int mod(998244353);
const int maxn(1e5);
const int blk(80);

inline void Inc(int &x, int y) {
	if ((x += y) >= mod) x -= mod;
}

int pr[maxn + 100], phi[maxn + 100], inv[maxn + 100], mu[maxn + 100], tot, f[maxn + 100];
int test, n, m, ans;
vector <int> g[maxn + 100], s[blk + 1][blk + 1];
bitset <maxn + 100> ispr;
  
int main() {
	register int i, j, k, len;
	mu[1] = phi[1] = inv[1] = 1, ispr[1] = 1;
	for (i = 2; i <= maxn; ++i) inv[i] = (ll)(mod - mod / i) * inv[mod % i] % mod;
	for (i = 2; i <= maxn; ++i) {
		if (!ispr[i]) pr[++tot] = i, mu[i] = -1, phi[i] = i - 1;
		for (j = 1; j <= tot && i * pr[j] <= maxn; ++j) {
			ispr[i * pr[j]] = 1;
			if (i % pr[j]) mu[i * pr[j]] = -mu[i], phi[i * pr[j]] = phi[i] * (pr[j] - 1);
			else {
				mu[i * pr[j]] = 0;
				phi[i * pr[j]] = phi[i] * pr[j];
				break;
			}
		}
	}
	for (i = 1; i <= maxn; ++i) Inc(mu[i], mod);
	for (i = 1; i <= maxn; ++i)
		for (j = i; j <= maxn; j += i) Inc(f[j], (ll)i * inv[phi[i]] % mod * mu[j / i] % mod);
	for (i = 1; i <= maxn; ++i) {
		len = maxn / i, g[i].resize(len + 1);
		for (j = 1; j <= len; ++j) g[i][j] = (g[i][j - 1] + phi[i * j]) % mod;
	}
	for (i = 1; i <= blk; ++i)
		for (j = i; j <= blk; ++j) {
			len = maxn / j, s[i][j].resize(len + 1);
			for (k = 1; k <= len; ++k) s[i][j][k] = (s[i][j][k - 1] + (ll)f[k] * g[k][i] % mod * g[k][j] % mod) % mod;
		}
	for (scanf("%d", &test); test; --test) {
		ans = 0, scanf("%d%d", &n, &m);
		if (n > m) swap(n, m);
		len = min(n, m / blk);
		for (i = 1; i <= len; ++i) Inc(ans, (ll)g[i][n / i] * g[i][m / i] % mod * f[i] % mod);
		for (i = len + 1; i <= n; i = j + 1) {
			j = min(n / (n / i), m / (m / i));
			Inc(ans, (s[n / i][m / i][j] - s[n / i][m / i][i - 1] + mod) % mod);
		}
		printf("%d\n", ans);
	}
    return 0;
}

猜你喜欢

转载自blog.csdn.net/oi_Konnyaku/article/details/85231786
今日推荐