luogu3455 [POI2007]ZAP-Queries 簡單的莫比烏斯反演
阿新 • • 發佈:2019-01-25
poi gcd www. swap sum () wap ace clas
link
ms是莫比烏斯反演裏最水的題。。。
題意:對於給定的整數a,b和d,有多少正整數對x,y,滿足x<=a,y<=b,並且gcd(x,y)=d。
多組詢問, T<=50000,d,a,b<=50000
稍微推下shizi
\(\sum_{i=1}^a\sum_{j=1}^b[\gcd(i,j)=d]\)
\(=\sum_{i=1}^{a/k}\sum_{j=1}^{b/k}[\gcd(i,j)=1]\)
\(=\sum_{i=1}^{a/k}\sum_{j=1}^{b/k}\sum_{d|i,d|j}\mu(d)\)
\(=\sum_{i=1}^{a/k}\sum_{j=1}^{b/k}\sum_{d|i,d|j}\mu(d)\)
\(=\sum_{d=1}^n\mu(d)\lfloor\frac a{kd}\rfloor\lfloor\frac b{kd}\rfloor\)
連枚舉倍數都不用。。。直接打個數論分塊就行了。。。復雜度\(O(T\sqrt n)\)
#include <cstdio> #include <functional> using namespace std; bool visit[50010]; int prime[50010], mu[50010], tot, fuck = 50000; int main() { mu[1] = 1; for (int i = 2; i <= fuck; i++) { if (visit[i] == false) prime[++tot] = i, mu[i] = -1; for (int j = 1; j <= tot && i * prime[j] <= fuck; j++) { visit[i * prime[j]] = true; if (i % prime[j] == 0) break; mu[i * prime[j]] = -mu[i]; } mu[i] += mu[i - 1]; } int t; scanf("%d", &t); while (t --> 0) { int n, m, k; scanf("%d%d%d", &n, &m, &k); n /= k, m /= k; int res = 0; if (n > m) swap(n, m); for (int i = 1, j; i <= n; i = j + 1) { j = min(n / (n / i), m / (m / i)); res += (mu[j] - mu[i - 1]) * (n / i) * (m / i); } printf("%d\n", res); } return 0; }
40行一遍AC
於NOIWC2019 Day2晚試機
日推裏出現的題,竟然挺水
NOI Linux真TM難用,累死我了
luogu3455 [POI2007]ZAP-Queries 簡單的莫比烏斯反演