首先是喜闻乐见的几个入门基础题,连题面基本都是一样的,流程是预处理mu函数,得到输入数据后整除分块(如果时间复杂度需要的话),思路主要是套用下图第二个公式:

莫比乌斯反演题目结(上)

(截图来自电科bilibili上的算法讲堂大家可以去看哦)

洛谷2257

题意:全部gcd(1~n,1~m)为质数的个数。

刚开始不用管他要求的数有什么特性,就列一般式子:

莫比乌斯反演题目结(上)

(截图来自pengym的博客题解)

但这个题用第二条推出的式子还得变一变,就直观感受去变!d的范围?n是质数?把F(d)提出去?

下图中T即为上图中的d,t即为n。

莫比乌斯反演题目结(上)

式子写到这里就可以写代码了,先把mu全加上,这样写:

1   rep(j, 1, cnt) {
2         for (int i = 1; i * primes[j] <= n; i++) {
3             g[primes[j] * i] += mu[i];
4         }
5     }

然后整除分块是某一块乘上的(n/T)*(m/T)是不变的,所以这一块一起算,代码是这样的:

1   rep(i, 1, n)    sum[i] = sum[i-1] + g[I];//这个是预处理
1         ll ans = 0ll;
2         for (int l = 1, r; l <= n; l = r + 1) {
3             r = min(n / (n / l), m / (m / l));
4             ans += (sum[r] - sum[l - 1]) * (n / l) * (m / l);
5         }

 

总代码(部分):

 1 void pre(int n) {
 2     mu[1] = 1;
 3     rep(i, 2, n) {
 4         if (!vis[i]) {
 5             mu[i] = -1;
 6             primes[++cnt] = i;
 7         }
 8         for (int j = 1; j <= cnt && primes[j] * i <= n; j++) {
 9             vis[primes[j] * i] = true;
10             if (i % primes[j] == 0)    break;
11             mu[primes[j] * i] = -mu[i];    
12         }
13     }
14 
15     rep(j, 1, cnt) {
16         for (int i = 1; i * primes[j] <= n; i++) {
17             g[primes[j] * i] += mu[i];
18         }
19     }
20     rep(i, 1, n)    sum[i] = sum[i-1] + g[i];
21 }
22 
23 int main() {
24     pre(maxn);
25     for (T = ri; T; T--) {
26         n = ri, m = ri;
27         if (n > m)    swap(n, m);
28 
29         ll ans = 0ll;
30         for (int l = 1, r; l <= n; l = r + 1) {
31             r = min(n / (n / l), m / (m / l));
32             ans += (sum[r] - sum[l - 1]) * (n / l) * (m / l);
33         }
34         printf("%lld\n", ans);
35     }
36     return 0;
37 }

 

HDU1695

莫比乌斯反演题目结(上)

 

(复习一下式子)

题意:gcd(1~b,1~d)== k的个数。

跟上一题很像,甚至这道题根本不用整除分块,也不用进一步推式子……就是求f(k),直接拿第二个式子扫一遍加和就行了。另外去个重,本题(x,y)和(y,x)算一种。

 1 void pre(int n) {
 2     mu[1] = 1;
 3     rep(i, 2, n) {
 4         if (!vis[i]) {
 5             primes[++cnt] = i;
 6             mu[i] = -1;
 7         }
 8         for (int j = 1; j <= cnt && primes[j] * i <= n; j++) {
 9             vis[primes[j] * i] = true;
10             if (i % primes[j] == 0)    break;
11             mu[primes[j] * i] = -mu[i];
12         }
13     }
14 }
15 
16 ll cal(int b, int d) {
17     ll ret = 0ll;
18     for (int i = 1; i * k <= b; i++) {
19         int t = i * k;
20         ret += (ll)mu[i] * (b / t) * (d / t);
21     }
22     return ret;
23 }
24 
25 int main() {
26     pre(maxn - 5);
27     for (int T = ri, i = 1; i <= T; i++) {
28         a = ri, b = ri, c = ri, d = ri, k = ri;
29         if (b > d)    swap(b, d);
30         printf("Case %d: %lld\n", i, k ? cal(b, d) - cal(b, b) / 2 : 0);
31     }
32     return 0;
33 }

 

BZOJ1101

n次询问gcd(1~a, 1~b) == d。同一道题。

 1 #pragma comment(linker, "/STACK:1024000000,1024000000")
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <cstdlib>
 5 #include <cmath>
 6 #include <ctime>
 7 #include <cctype>
 8 #include <climits>
 9 #include <iostream>
10 #include <iomanip>
11 #include <algorithm>
12 #include <string>
13 #include <sstream>
14 #include <stack>
15 #include <queue>
16 #include <set>
17 #include <map>
18 #include <vector>
19 #include <list>
20 #include <fstream>
21 #include <bitset>
22 #define init(a, b) memset(a, b, sizeof(a))
23 #define rep(i, a, b) for (int i = a; i <= b; i++)
24 #define irep(i, a, b) for (int i = a; i >= b; i--)
25 using namespace std;
26 
27 typedef double db;
28 typedef long long ll;
29 typedef unsigned long long ull;
30 typedef pair<int, int> P;
31 const int inf = 0x3f3f3f3f;
32 const ll INF = 1e18;
33 
34 template <typename T> void read(T &x) {
35     x = 0;
36     int s = 1, c = getchar();
37     for (; !isdigit(c); c = getchar())
38         if (c == '-')    s = -1;
39     for (; isdigit(c); c = getchar())
40         x = x * 10 + c - 48;
41     x *= s;
42 }
43 
44 template <typename T> void write(T x) {
45     if (x < 0)    x = -x, putchar('-');
46     if (x > 9)    write(x / 10);
47     putchar(x % 10 + '0');
48 }
49 
50 template <typename T> void writeln(T x) {
51     write(x);
52     puts("");
53 }
54 
55 const int maxn = 5e4 + 5;
56 int n, a, b, d;
57 int mu[maxn], primes[maxn], tot, sum[maxn];
58 bool vis[maxn];
59 
60 void pre(int n) {
61     mu[1] = 1;
62     rep(i, 2, n) {
63         if (!vis[i]) {
64             primes[++tot] = i;
65             mu[i] = -1;
66         }
67         for (int j = 1; j <= tot && primes[j] * i <= n; j++) {
68             vis[primes[j] * i] = true;
69             if (i % primes[j] == 0)    break;
70             mu[primes[j] * i] = - mu[i];
71         }
72     }
73     rep(i, 1, n)    sum[i] = sum[i - 1] + mu[i];
74 }
75 
76 ll solve(int n, int m) {
77     if (n > m)    swap(n, m);
78     ll ret = 0ll;
79     for (int l = 1, r; l <= n; l = r + 1) {
80         r = min(n / (n / l), m / (m / l));
81         ret += (ll)(sum[r] - sum[l - 1]) * (n / l) * (m / l);
82     }
83     return ret;
84 }
85 
86 int main() {
87     pre(maxn - 5);
88     for (read(n); n; n--) {
89         read(a), read(b), read(d);
90         writeln(solve(a / d, b / d));
91     }
92     return 0;
93 }
bzoj1101

相关文章:

  • 2021-10-08
猜你喜欢
  • 2022-12-23
  • 2021-12-08
  • 2021-08-04
  • 2022-02-22
  • 2021-10-17
  • 2022-01-07
相关资源
相似解决方案