• 莫比乌斯反演题目结(下)


    莫比乌斯题目结(上)

    BZOJ3994

    大佬们推公式的手段是怎么学到的……qwq完全想不到啊qwq

    学习的是这篇博客的推公式。

    要点节选:

    1.结论:d(i*j)是i*j的约数个数,则

    2.又用到莫比乌斯函数的性质

    3.枚举项的更换。约数整除枚举的和搭配真值式往往可以替代为常数块,而直接枚举符合真值的数可以省去真值。

    数学推导出来以后,代码就不复杂了。

     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 T, n, m;
    57 int mu[maxn], primes[maxn], tot;
    58 ll sum[maxn], g[maxn];
    59 bool vis[maxn];
    60 
    61 void pre(int n) {
    62     mu[1] = 1;
    63     rep(i, 2, n) {
    64         if (!vis[i]) {
    65             mu[i] = -1;
    66             primes[++tot] = i;
    67         }
    68         for (int j = 1; j <= tot && primes[j] * i <= n; j++) {
    69             vis[primes[j] * i] = true;
    70             if (i % primes[j] == 0)    break;
    71             mu[primes[j] * i] = -mu[i];
    72         }
    73     }
    74     rep(i, 1, n)    sum[i] = sum[i - 1] + mu[i];
    75     rep(t, 1, n) {
    76         ll tmp = 0ll;
    77         for (int l = 1, r; l <= t; l = r + 1) {
    78             r = t / (t / l);
    79             tmp += (ll)(r - l + 1) * (t / l);
    80         }
    81         g[t] = tmp;
    82     }
    83 }
    84 
    85 int main() {
    86     pre(maxn - 5);
    87     for (read(T); T; T--) {
    88         read(n), read(m);
    89         if (n > m)    swap(n, m);
    90         ll ans = 0ll;
    91         for (int l = 1, r; l <= n; l = r + 1) {
    92             r = min(n / (n / l), m / (m / l));
    93             ans += (sum[r] - sum[l - 1]) * g[n / l] * g[m / l];
    94         }
    95         writeln(ans);
    96     }
    97     return 0;
    98 }
    bzoj3994

    BZOJ3529

    首先是得推公式, 学习的这个PPT,核心:

    这公式根本想不到啊嘤~

    那么这样子以后就是操作问题了:1.离线,按a的大小把询问排序;2.不断往树状数组里插入符合当前a值的F*mu;3.对于每个询问a,分块得到ans,这时往常的sum[r]-sum[l-1]就用BIT的query(r) - query(l-1)来得到了,特殊的前缀和。3.取模的方法也很有趣,自由爆int……

      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 = 1e5 + 5, maxq = 2e4 + 5;
     56 int n, m, a, Q, mx;
     57 int mu[maxn], primes[maxn], tot, ans[maxq];
     58 bool vis[maxn];
     59 P F[maxn];
     60 
     61 struct node {
     62     int n, m, a, id;
     63 
     64     bool operator < (const node &b) const {
     65         return a < b.a;
     66     }
     67 }T[maxq];
     68 
     69 struct BIT {
     70     int t[maxn];
     71 
     72     void add(int x, int val) {
     73         for (int i = x; i <= mx; i += i&-i)
     74             t[i] += val;
     75     }
     76 
     77     int query(int x) {
     78         int ret = 0;
     79         for (int i = x; i; i -= i&-i)
     80             ret += t[i];
     81         return ret;
     82     }
     83 }bit;
     84 
     85 void pre(int n) {
     86     mu[1] = 1;
     87     rep(i, 2, n) {
     88         if (!vis[i]) {
     89             mu[i] = -1;
     90             primes[++tot] = i;
     91         }
     92         for (int j = 1; j <= tot && primes[j] * i <= n; j++) {
     93             vis[primes[j] * i] = true;
     94             if (i % primes[j] == 0)    break;
     95             mu[primes[j] * i] = -mu[i];
     96         }
     97     }
     98     rep(i, 1, n) {
     99         for (int j = i; j <= n; j += i) {
    100             F[j].first += i;
    101         }
    102     }
    103     rep(i, 1, n)    F[i].second = i;
    104 }
    105 
    106 void solve(int i) {
    107     int id = T[i].id, n = T[i].n, m = T[i].m;
    108     for (int l = 1, r; l <= n; l = r + 1) {
    109         r = min(n / (n / l), m / (m / l));
    110         ans[id] += (n / l) * (m / l) * (bit.query(r) - bit.query(l - 1));
    111     }
    112 }
    113 
    114 int main() {
    115     read(Q);
    116     rep(i, 1, Q) {
    117         read(n), read(m), read(a);
    118         if (n > m)    swap(n, m);
    119         T[i] = {n, m, a, i};
    120         mx = max(mx, n);
    121     }
    122     pre(mx);
    123     sort(F + 1, F + 1 + mx);
    124     sort(T + 1, T + 1 + Q);
    125     int now = 0;
    126     rep(i, 1, Q) {
    127         while(now + 1 <= mx && F[now + 1].first <= T[i].a) {
    128             now++;
    129             for (int j = F[now].second; j <= mx; j += F[now].second)
    130                 bit.add(j, F[now].first * mu[j / F[now].second]);
    131         }
    132         solve(i);
    133     }
    134     rep(i, 1, Q)    writeln(ans[i]&0x7fffffff);
    135     return 0;
    136 }
    bzoj3529

    bzoj:4816、题单题单题单、洛谷试炼场专题

    -----未完待续-----

  • 相关阅读:
    Ubuntu虚拟机磁盘空间不足的解决
    eclipse启动报错 JVM terminated. Exit code=1
    Ubuntu16.04 安装eclipse
    HDU 1710 Binary Tree Traversals(二叉树)
    Ubuntu16.04 搭建伪分布式Hadoop环境
    HDU 1560 DNA sequence(IDA*)
    Go的函数
    Go的包
    Go语言开发环境搭建
    go的循环
  • 原文地址:https://www.cnblogs.com/AlphaWA/p/10492681.html
Copyright © 2020-2023  润新知