[SDOI2014]数表 莫比乌斯反演

~~~题面~~~

题解:

设$f(d)$表示数$d$的约数和,那么$(i, j)$中的数为$f(gcd(i, j))$,
那么有2种枚举方法。
1,枚举每一格看对应的$f(d)$是几.$$ans = \sum_{i = 1}^{n}\sum_{j = 1}^{m}{f(gcd(i, j))}$$
2,枚举$d$看有哪些格子的$f$值为$f(d)$.
$$ans = \sum_{i = 1}^{min(n, m)}{f(d)}\sum_{x = 1}^{n}\sum_{y = 1}^{m}[gcd(x, y) == d]$$
显然后者更加方便。
所以$$ans = \sum_{i = 1}^{min(n, m)}{f(d)}\sum_{x = 1}^{n}\sum_{y = 1}^{m}[gcd(x, y) == d]$$
$$ans = \sum_{i = 1}^{min(n, m)}{f(d)}\sum_{x = 1}^{\lfloor{\frac{n}{d}}\rfloor}\sum_{y = 1}^{\lfloor{\frac{m}{d}}\rfloor}[gcd(x, y) == 1]$$
$$ans = \sum_{i = 1}^{min(n, m)}{f(d)}\sum_{x = 1}^{\lfloor{\frac{n}{d}}\rfloor}\sum_{y = 1}^{\lfloor{\frac{m}{d}}\rfloor}\sum_{t | gcd(x, y)}{\mu(t)}$$
$$\sum_{i = 1}^{min(n, m)}f(d)\sum_{t = 1}^{min(\lfloor{\frac{n}{d}}\rfloor, \lfloor{\frac{m}{d}}\rfloor)}{\lfloor{\frac{\lfloor{\frac{n}{d}}\rfloor}{t}}\rfloor}{\lfloor{\frac{\lfloor{\frac{m}{d}}\rfloor}{t}}\rfloor}\mu(t)$$<---看有多少对$(x, y)$统计到了$\mu(t)$(即为$\mu(t)$的倍数/有因子$\mu(t)$)
$$\sum_{i = 1}^{min(n, m)}f(d)\sum_{t =1}^{min(\lfloor{\frac{n}{d}}\rfloor, \lfloor{\frac{m}{d}}\rfloor)}{\lfloor{\frac{n}{td}\rfloor}}{\lfloor{\frac{m}{td}\rfloor}}\mu(t)$$
令$T = td$,则
$$ans = \sum_{T = 1}^{min(n, m)}{\lfloor{\frac{n}{T}}\rfloor \lfloor{\frac{m}{T}}\rfloor} \sum_{d|T}f(d)\mu(\frac{T}{d})$$
因为$T = td$,所以符合要求的$d$满足$d|T$.
设$$g(T) = \sum_{d | T}f(d)\mu(\frac{T}{d}) \Longleftrightarrow f(T) = \sum_{d | T}g(d)$$
则$$ans = \sum_{T = 1}^{min(n, m)}{\lfloor{\frac{n}{T}}\rfloor \lfloor{\frac{m}{T}}\rfloor} g(T)$$
但是由于有$a$的限制,对于不同的$a$,$g(T)$的值是不同的,因此先筛出$f$数组,然后将$f$按$f_{i}$排序,离线询问,一个一个把符合条件的$f(d)$加入$g$数组,也就是每次处理询问时再暴力将$f(d)$的贡献加给满足$d|T$的$g(T)$,但是由于要维护$g$数组的前缀和,因此用树状数组维护$g$数组
根据$f$数组的定义,
当$x\quad mod \quad p_{i} \quad != \quad 0$有$f(x \cdot P_{i}) = f(x) + f(x) \cdot P_{i}$,其中$P_{i}$是质数
否则有$f(x \cdot p_{i}) = f(x) \cdot p_{i} + f(t)$,其中$t$为$x$除去质因数$p_{i}$后的值

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 #define R register int
  4 #define AC 101000
  5 #define ac 100000
  6 #define LL long long
  7 #define p 2147483648LL
  8 int t, tot, l;
  9 int prime[AC], mu[AC];
 10 LL g[AC];
 11 bool z[AC];
 12 struct node{
 13     int n, m, a, id;LL ans;
 14 }s[AC];
 15 struct kkk{
 16     int d;
 17     LL w;
 18 }f[AC];
 19
 20 inline int read()
 21 {
 22     int x = 0;char c = getchar();
 23     while(c > ‘9‘ || c < ‘0‘) c = getchar();
 24     while(c >= ‘0‘ && c <= ‘9‘) x = x * 10 + c - ‘0‘, c = getchar();
 25     return x;
 26 }
 27
 28 inline bool cmp(node a, node b)
 29 {
 30     return a.a < b.a;
 31 }
 32
 33 inline bool cmp1(kkk a, kkk b)
 34 {
 35     return a.w < b.w;
 36 }
 37
 38 inline int lowbit(int x)
 39 {
 40     return x & (-x);
 41 }
 42
 43 inline void add(int x, int S)
 44 {
 45 //    if(x <= 4)printf("add %d : %d\n", x, S);
 46     for(R i = x; i <= ac; i += lowbit(i)) g[i] += S;
 47 }
 48
 49 inline LL find(int x)
 50 {
 51     LL rnt = 0;
 52     for(R i = x; i; i -= lowbit(i)) rnt += g[i];
 53     return rnt;
 54 }
 55
 56 void pre()
 57 {
 58     t = read();
 59     for(R i = 1; i <= t; i++)
 60         s[i].n = read(), s[i].m = read(), s[i].a = read(), s[i].id = i;
 61     sort(s + 1, s + t + 1, cmp);
 62 }
 63
 64 void get()
 65 {
 66     int x;
 67     f[1] =(kkk){1, 1}, mu[1] = 1;
 68     for(R i = 2; i <= ac; i++)
 69     {
 70         f[i].d = i;
 71         if(!z[i]) prime[++tot] = i, f[i].w = i + 1, mu[i] = -1;
 72         for(R j = 1; j <= tot; j++)
 73         {
 74             x = prime[j];
 75             if(x * i > ac) break;
 76             z[x * i] = true;
 77             if(!(i % x))
 78             {
 79                 int t = i;
 80                 while(!(t % x)) t /= x;
 81                 f[x * i].w = f[t].w + f[i].w * x;
 82                 break;
 83             }
 84             mu[x * i] = -mu[i];
 85             f[x * i].w = f[i].w + f[i].w * x;
 86         }
 87     }
 88     sort(f + 1, f + ac + 1, cmp1);
 89 }
 90
 91 void build(int a)//更新树状数组
 92 {
 93     for(R i = l + 1; i <= ac; i++)
 94     {
 95         if(f[i].w > a) return ;
 96         ++l;
 97         for(R j = f[i].d; j <= ac; j += f[i].d)
 98             add(j, f[i].w * mu[j / f[i].d]);
 99     }
100 }
101
102 inline bool cmp2(node a, node b)
103 {
104     return a.id < b.id;
105 }
106
107 void work()
108 {
109     for(R i = 1; i <= t; i++)
110     {
111         build(s[i].a);
112         int b = min(s[i].n, s[i].m), pos;
113         for(R j = 1; j <= b; j = pos + 1)
114         {
115             pos = min(s[i].n / (s[i].n / j), s[i].m / (s[i].m / j));
116             s[i].ans += (s[i].n / j) * (s[i].m / j) * (find(pos) - find(j - 1));
117             s[i].ans = (s[i].ans + p) % p;//取模error!!!取模的时候记得+p....
118         }//error!!!无论何时都要+p并取模,,因为可能前面取模后再减就变负数了。。。。加个判断就应对不了负数的情况了
119     //    printf("\n");
120     }
121     sort(s + 1, s + t + 1, cmp2);
122     for(R i = 1; i <= t; i++) printf("%lld\n", s[i].ans);
123 }
124
125 int main()
126 {
127     freopen("in.in", "r", stdin);
128     //freopen("sdoi2014shb.in", "r", stdin);
129     //freopen("sdoi2014shb.out", "w", stdout);
130     pre();
131     get();
132     work();
133     fclose(stdin);
134     //fclose(stdout);
135     return 0;
136 }

原文地址:https://www.cnblogs.com/ww3113306/p/9488799.html

时间: 2024-10-05 23:25:15

[SDOI2014]数表 莫比乌斯反演的相关文章

bzoj [SDOI2014]数表 莫比乌斯反演 BIT

bzoj [SDOI2014]数表 莫比乌斯反演 BIT 链接 bzoj luogu loj 思路 \[ \sum\limits_{i=1}^{n}\sum\limits_{j=1}^{m}a*[f[gcd(i,j)]<=a] \] \[ f[]可以O(n)预处理出来 \] \[ \sum\limits_{k=1}^{n}f[k]*\sum\limits_{i=1}^{m}\sum\limits_{j=1}^{m}[gcd(i,j)==k] \] \[ \sum\limits_{k=1}^{n}

【BZOJ3529】[Sdoi2014]数表 莫比乌斯反演+树状数组

[BZOJ3529][Sdoi2014]数表 Description 有一张N×m的数表,其第i行第j列(1 < =i < =礼,1 < =j < =m)的数值为能同时整除i和j的所有自然数之和.给定a,计算数表中不大于a的数之和. Input 输入包含多组数据.    输入的第一行一个整数Q表示测试点内的数据组数,接下来Q行,每行三个整数n,m,a(|a| < =10^9)描述一组数据. Output 对每组数据,输出一行一个整数,表示答案模2^31的值. Sample I

BZOJ 3529: [Sdoi2014]数表 [莫比乌斯反演 树状数组]

3529: [Sdoi2014]数表 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 1399  Solved: 694[Submit][Status][Discuss] Description 有一张N×m的数表,其第i行第j列(1 < =i < =礼,1 < =j < =m)的数值为能同时整除i和j的所有自然数之和.给定a,计算数表中不大于a的数之和. Input 输入包含多组数据.    输入的第一行一个整数Q表示测试点内的数据

bzoj 3529 [Sdoi2014]数表 (莫比乌斯反演+树状数组+离线)

题目大意:有一张$n*m$的数表,第$i$行第$j$列的数是同时能整除$i,j$的所有数之和,求数表内所有不大于A的数之和 先是看错题了...接着看对题了发现不会做了...刚了大半个下午无果 看了Po姐的题解(Orzzz)才搞懂这道题,搞清楚了莫比乌斯反演的两种经典的卷积形式的不同之处 令$\sigma(i)$表示i的约数个数和 如果去掉A这个限制,则题目是让我们求$\sum_{i=1}^{n}\sum_{j=1}^{m}\sigma(gcd(i,j))$ 考虑如何正确转化式子,让我们能够把不大

BZOJ 3529([Sdoi2014]数表-莫比乌斯反演)

有一张N×m的数表,其第i行第j列(1 < =i < =n,1 < =j < =m)的数值为能同时整除i和j的所有自然数之和.给定a,计算数表中不大于a的数之和模2^31的值模2^31的值. 1<=n.m<=10 5 ,Q<=2×10 4  组询问 记k的约数和f(k) 求∑ n i=1 ∑ m j=1 gcd(i,j)[f(gcd(i,j))≤a] #include<bits/stdc++.h> using namespace std; #defin

bzoj 3529 数表 莫比乌斯反演+树状数组

题目大意: 有一张N×m的数表,其第i行第j列(1 < =i < =礼,1 < =j < =m)的数值为能同时整除i和j的所有自然数之和.给定a,计算数表中不大于a的数之和. http://wenku.baidu.com/link?url=1zHluup-GXHdByoQXhMRwRu22Uu15y4DztIr1_hKVxjHJmuLQF4_01UQhLEOR7RJIpsGyfD_5fXrx9DE7sY6JeukaNUY83In097GjUOmZ7K ppt课件中讲的很仔细了 1

BZOJ 3529 数表(莫比乌斯反演)

http://www.lydsy.com/JudgeOnline/problem.php?id=3529 思路:令F(i)为i的约数和, 1<=x<=n,1<=y<=m G(i)为i|gcd(x,y)的个数 g(i)为i=gcd(x,y)的个数 G(i)=floor(n/i)*floor(m/i) g(i)=Σu(d/i)*G(d) (i|d) F(i)可以用线性筛O(n)处理 ans=(1<=i<=min(n,m)) Σg(i)*F(i)=Σ F(i)*ΣG(d)*u

莫比乌斯反演2

\documentclass[12pt,UTF8,titlepage]{article} \usepackage[colorlinks,linkcolor=blue]{hyperref} \usepackage{fontspec} \usepackage{xunicode} \usepackage{xltxtra} \usepackage{amstext} \usepackage{amsmath} \usepackage{amssymb} \usepackage{listings} \usepa

BZOJ 3529: [Sdoi2014]数表

Description 有一张N×m的数表,其第i行第j列(1 < =i < =n,1 < =j < =m)的数值为能同时整除i和j的所有自然数之和.给定a,计算数表中不大于a的数之和. HINT 1 < =N.m < =10^5  , 1 < =Q < =2×10^4 Solution 先假设a的限制不存在 正面把答案强行写出来是这样的 其中F(i)为i的约数和,可以线性筛处理 然后慢慢化简其中的各个部分 令g(i)为1<=x<=n,1<