欢迎访问 生活随笔!

生活随笔

当前位置: 首页 > 编程资源 > 编程问答 >内容正文

编程问答

mobius初步

发布时间:2023/12/4 编程问答 40 豆豆
生活随笔 收集整理的这篇文章主要介绍了 mobius初步 小编觉得挺不错的,现在分享给大家,帮大家做个参考.
  • ∑i=1n∑j=1m(gcd(i,j)==1)\sum_{i = 1} ^{n} \sum_{j = 1} ^{m} (gcd(i, j) == 1)i=1nj=1m(gcd(i,j)==1)

    我们引入一个知识∑d∣nμ(d)=(n==1)\sum_{d \mid n} \mu(d) = (n == 1)dnμ(d)=(n==1)

    所以gcd(i,j)=∑d∣gcd(i,j)μ(d)gcd(i, j) = \sum_{d \mid gcd(i, j)} \mu(d)gcd(i,j)=dgcd(i,j)μ(d)

    对上式进行化简:

    =∑i=1n∑j=1m∑d∣gcd(i,j)μ(d)= \sum_{i = 1} ^{n} \sum_{j = 1} ^{m} \sum_{d\mid gcd(i, j)} \mu(d)=i=1nj=1mdgcd(i,j)μ(d)

    =∑d∣nμ(d)∑i=1nd∑j=1md1= \sum_{d \mid n} \mu(d) \sum_{i = 1} ^{\frac{n}{d}} \sum_{j = 1}^{\frac{m}{d}}1=dnμ(d)i=1dnj=1dm1

    ∑d=1nμ(d)ndmd\sum_{d = 1} ^{n} \mu(d) \frac{n}{d} \frac{m}{d}d=1nμ(d)dndm

    最后利用整除分块求得最后的答案

  • ∑i=1n∑j=1m(gcd(i,j)==k)\sum_{i = 1} ^{n} \sum_{j = 1} ^{m} (gcd(i, j) == k)i=1nj=1m(gcd(i,j)==k)

    =∑i=1nk∑j=1md(gcd(i,j)==1)= \sum_{i = 1} ^{\frac{n}{k}} \sum_{j = 1} ^{\frac{m}{d}} (gcd(i, j) == 1)=i=1knj=1dm(gcd(i,j)==1)

    n′=nk,m′=mkn' = \frac{n}{k}, m' = \frac{m}{k}n=kn,m=km,所以如上式:

P3455 [POI2007]ZAP-Queries

上面式子的模板题,就不过多讲解了,直接上代码

/*Author : lifehappy */ // #pragma GCC optimize(2) // #pragma GCC optimize(3) #include <bits/stdc++.h>#define mp make_pair #define pb push_back #define endl '\n' #define mid (l + r >> 1) #define lson rt << 1, l, mid #define rson rt << 1 | 1, mid + 1, r #define ls rt << 1 #define rs rt << 1 | 1using namespace std;typedef long long ll; typedef unsigned long long ull; typedef pair<int, int> pii;const double pi = acos(-1.0); const double eps = 1e-7; const int inf = 0x3f3f3f3f;inline ll read() {ll x = 0, f = 1; char c = getchar();while(c < '0' || c > '9') {if(c == '-') f = -1;c = getchar();}while(c >= '0' && c <= '9') {x = (x << 1) + (x << 3) + (c ^ 48);c = getchar();}return x * f; }const int N = 5e4 + 10;int mu[N], a, b, d;bool st[N];vector<int> prime;void mobius() {st[1] = st[0] = mu[1] = 1;for(int i = 2; i < N; i++) {if(!st[i]) {prime.pb(i);mu[i] = -1;}for(int j = 0; j < prime.size() && i * prime[j] < N; j++) {st[i * prime[j]] = 1;if(i % prime[j] == 0) {mu[i * prime[j]] = 0;break;}mu[i * prime[j]] = -mu[i];}}for(int i = 1; i < N; i++) mu[i] += mu[i - 1]; }int main() {// freopen("in.txt", "r", stdin);// freopen("out.txt", "w", stdout);// ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);mobius();int T = read();while(T--) {a = read(), b = read(), d = read();int n = a /= d, m = b /= d;if(n > m) swap(n, m);ll ans = 0;for(int l = 1, r; l <= n; l = r + 1) {r = min(n / (n / l), m / (m / l));ans += 1ll * (mu[r] - mu[l - 1]) * (n / l) * (m / l);}printf("%lld\n", ans);}return 0; }

P2522 [HAOI2011]Problem b

也是是模板题,只是稍加改动,类似于前缀和的取法,最后得到我们的答案。

/*Author : lifehappy */ // #pragma GCC optimize(2) // #pragma GCC optimize(3) #include <bits/stdc++.h>#define mp make_pair #define pb push_back #define endl '\n' #define mid (l + r >> 1) #define lson rt << 1, l, mid #define rson rt << 1 | 1, mid + 1, r #define ls rt << 1 #define rs rt << 1 | 1using namespace std;typedef long long ll; typedef unsigned long long ull; typedef pair<int, int> pii;const double pi = acos(-1.0); const double eps = 1e-7; const int inf = 0x3f3f3f3f;inline ll read() {ll x = 0, f = 1; char c = getchar();while(c < '0' || c > '9') {if(c == '-') f = -1;c = getchar();}while(c >= '0' && c <= '9') {x = (x << 1) + (x << 3) + (c ^ 48);c = getchar();}return x * f; }const int N = 5e4 + 10;int mu[N], a, b, c, d, k;bool st[N];vector<int> prime;void mobius() {st[1] = st[0] = mu[1] = 1;for(int i = 2; i < N; i++) {if(!st[i]) {prime.pb(i);mu[i] = -1;}for(int j = 0; j < prime.size() && i * prime[j] < N; j++) {st[i * prime[j]] = 1;if(i % prime[j] == 0) {mu[i * prime[j]] = 0;break;}mu[i * prime[j]] = -mu[i];}}for(int i = 1; i < N; i++) mu[i] += mu[i - 1]; }ll solve(int a, int b, int d) {int n = a /= d, m = b /= d;if(n > m) swap(n, m);ll ans = 0;for(int l = 1, r; l <= n; l = r + 1) {r = min(n / (n / l), m / (m / l));ans += 1ll * (mu[r] - mu[l - 1]) * (n / l) * (m / l);}return ans; }int main() {// freopen("in.txt", "r", stdin);// freopen("out.txt", "w", stdout);// ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);mobius();int T = read();while(T--) {a = read(), b = read(), c = read(), d = read(), k = read();ll ans = solve(b, d, k) + solve(a - 1, c - 1, k) - solve(a - 1, d, k) - solve(b, c - 1, k);printf("%lld\n", ans);}return 0; }
  • ∑i=1n∑j=1mij(gcd(i,j)==k)\sum_{i = 1} ^{n} \sum_{j = 1} ^{m} ij(gcd(i, j) == k)i=1nj=1mij(gcd(i,j)==k)

    =k2∑i=1nk∑j=1mkij(gcd(i,j)==1)= k ^ 2\sum_{i = 1} ^{\frac{n}{k}} \sum_{j = 1} ^{\frac{m}{k}}ij(gcd(i, j) == 1)=k2i=1knj=1kmij(gcd(i,j)==1)

    =k2∑i=1nk∑j=1mkij∑d∣gcd(i,j)μ(d)= k ^ 2\sum_{i = 1} ^{\frac{n}{k}} \sum_{j = 1} ^{\frac{m}{k}}ij\sum_{d\mid gcd(i, j)} \mu(d)=k2i=1knj=1kmijdgcd(i,j)μ(d)

    =k2∑d=1nkμ(d)∑i=1nk∑j=1mkij= k ^ 2\sum_{d = 1} ^{\frac{n}{k}} \mu(d)\sum_{i = 1} ^{\frac{n}{k}} \sum_{j = 1} ^{\frac{m}{k}}ij=k2d=1knμ(d)i=1knj=1kmij

    =k2∑d=1nkμ(d)d2∑i=1nkd∑j=1mkdij= k ^ 2\sum_{d = 1} ^{\frac{n}{k}} \mu(d)d ^ 2\sum_{i = 1} ^{\frac{n}{kd}} \sum_{j = 1} ^{\frac{m}{kd}}ij=k2d=1knμ(d)d2i=1kdnj=1kdmij

    ∑i=1nkd∑j=1mkdij\sum_{i = 1} ^{\frac{n}{kd}} \sum_{j = 1} ^{\frac{m}{kd}}iji=1kdnj=1kdmij这一项可以通过整除分块得到,最后再统计一遍答案就行。

总结

以上是生活随笔为你收集整理的mobius初步的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。