标签:ret void const cer == begin break efi foreach
好久没有写反演了 感觉不会了
首先推一个经典的式子啊
\[ans = \sum_{D=1}^{n}\sum_{d|D}f(d)\mu(\frac{D}{d})\frac{n}{D}\frac{m}{D}\]
记\(g(D) = \sum_{d|D}f(d)\mu(\frac{D}{d})\)
结论挺好找的啊
把一个数拆成\({p_k}^{a_k}\)形式
如果所有\(a_k\)相同 那么\(g(D) = (-1)^{k+1}\)
否则\(g(D) = 0\)
证明就考虑两个集合
所有次幂为最大的集合\(A\)非最大的集合\(B\)
\(f\)其实取决于\(A\)
\(\mu\)取决于选取的总个数
如果所有\(a_k\)相同 都可以使得\(\mu\)奇偶相同从而是0
但是如果选了A整个集合 要多减一个1
那么答案是\((-1)^{k+1}\)
否则都可以使得\(\mu\)奇偶相同从而是0
复杂度\(\mathcal O(T \sqrt n + n)\)
#include <bits/stdc++.h>
#define int long long
#define fo(i, n) for(int i = 1; i <= (n); i ++)
#define out(x) cerr << #x << " = " << x << "\n"
#define type(x) __typeof((x).begin())
#define foreach(it, x) for(type(x) it = (x).begin(); it != (x).end(); ++ it)
using namespace std;
// by piano
template<typename tp> inline void read(tp &x) {
x = 0;char c = getchar(); bool f = 0;
for(; c < '0' || c > '9'; f |= (c == '-'), c = getchar());
for(; c >= '0' && c <= '9'; x = (x << 3) + (x << 1) + c - '0', c = getchar());
if(f) x = -x;
}
template<typename tp> inline void arr(tp *a, int n) {
for(int i = 1; i <= n; i ++)
cout << a[i] << " ";
puts("");
}
const int N = 1e7 + 233;
#define P pair<int, int>
int np[N], g[N], p[N], p_cnt = 0;
P f[N];
inline void seive(int n) {
np[1] = 1; f[1] = P(0, 1); g[1] = 0;
for(int i = 2; i <= n; i ++) {
if(!np[i]) p[++ p_cnt] = i, f[i] = P(1, 1), g[i] = 1;
for(int j = 1; j <= p_cnt && p[j] * i <= n; j ++) {
int k = i * p[j];
np[k] = 1;
if(i % p[j] == 0) {
int del = f[i].first;
f[k] = P(del, f[i].second + 1);
if(del == 1) g[k] = 1;
else g[k] = f[k].second == f[del].second ? -g[del] : 0;
break;
}
else {
int del = i;
f[k] = P(i, 1);
if(del == 1) g[k] = 1;
else g[k] = f[k].second == f[del].second ? -g[del] : 0;
}
}
}
fo(i, n) g[i] += g[i - 1];
}
inline int F(int n, int m) {
return n * m;
}
inline int doit(int n, int m) {
if(n > m) swap(n, m);
int ans = 0;
for(int i = 1, last = 0; i <= n; i = last + 1) {
last = min(n / (n / i), m / (m / i));
ans += F(n / i, m / i) * (g[last] - g[i - 1]);
}
return ans;
}
main(void) {
seive(N);
int T;
for(read(T); T --;) {
int a, b;
cin >> a >> b;
cout << doit(a, b) << "\n";
}
}
莫比乌斯反演 bzoj 3309 DZY Loves Math
标签:ret void const cer == begin break efi foreach
原文地址:https://www.cnblogs.com/foreverpiano/p/9032855.html