link

\(\sum_{i=1}^n\sum_{j=1}^m[s(\gcd(i,j))\le a]s(\gcd(i,j))\)

\(=\sum_{p=1}^ns(p)[s(p)\le a]\sum_{i=1}^n\sum_{j=1}^m[\gcd(i,j)=p]\)

\(=\sum_{p=1}^ns(p)[s(p)\le a]\sum_{i=1}^{n/p}\sum_{j=1}^{m/p}[\gcd(i,j)=1]\)

\(=\sum_{p=1}^ns(p)[s(p)\le a]\sum_{i=1}^{n/p}\sum_{j=1}^{m/p}\sum_{d|i,d|j}\mu(d)\)

\(=\sum_{p=1}^ns(p)[s(p)\le a]\sum_{d=1}^n\mu(d)\lfloor\frac n{pd}\rfloor\lfloor\frac m{pd}\rfloor\)

\(=\sum_{q=1}^n\sum_{p|q}s(p)[s(p)\le a]\mu(\frac q p)\lfloor\frac n{pd}\rfloor\lfloor\frac m{pd}\rfloor\)

离线,将询问按照\(a\)排序

由于前面最多只有nlogn个,可以线性筛之后都存一下,存一个三元组(p, s(p), 那一大坨子),按照s(p)排序

离线处理询问,往树状数组里插值就行了,每次相当于在树状数组里查询前缀和之差,和普通的整除分块没什么太大的区别

#include <cstdio>
#include <algorithm>
#include <utility>
using namespace std; struct query
{
int n, m, a, id, ans;
} ask[20010]; struct info
{
int val, id;
} inf[100010]; int q;
bool vis[100010];
int d[100010], d1[100010], mu[100010], prime[100000], tot, fuck = 100000; int c[100010]; void chenge(int x, int y)
{
for (int i = x; i <= fuck; i += i & -i) c[i] += y;
} int getsum(int x)
{
int ans = 0;
for (int i = x; i > 0; i -= i & -i) ans += c[i];
return ans;
} void add(int p)
{
for (int q = p, dd = 1; q <= fuck; q += p, dd++)
chenge(q, d[p] * mu[dd]);
} int main()
{
scanf("%d", &q);
for (int i = 1; i <= q; i++)
{
scanf("%d%d%d", &ask[i].n, &ask[i].m, &ask[i].a);
ask[i].id = i;
}
sort(ask + 1, ask + 1 + q, [](const query &a, const query &b) { return a.a < b.a; }); mu[1] = d[1] = d1[1] = 1;
for (int i = 2; i <= fuck; i++)
{
if (vis[i] == false) prime[++tot] = i, mu[i] = -1, d[i] = d1[i] = i + 1;
for (int j = 1; j <= tot && i * prime[j] <= fuck; j++)
{
vis[i * prime[j]] = true;
if (i % prime[j] == 0)
{
d1[i * prime[j]] = d1[i] * prime[j] + 1;
d[i *prime[j]] = d[i] / d1[i] * d1[i * prime[j]];
break;
}
d1[i * prime[j]] = prime[j] + 1;
d[i * prime[j]] = d[i] * (prime[j] + 1);
mu[i * prime[j]] = -mu[i];
}
} for (int i = 1; i <= fuck; i++)
inf[i].id = i, inf[i].val = d[i]; sort(inf + 1, inf + 1 + fuck, [](const info &a, const info &b) { return a.val < b.val; }); for (int i = 1, j = 1; i <= q; i++)
{
while (j <= fuck && inf[j].val <= ask[i].a) { add(inf[j].id), j++; }
int n = ask[i].n, m = ask[i].m; if (n > m) swap(n, m);
int ans = 0;
for (int i = 1, j; i <= n; i = j + 1)
{
j = min(n / (n / i), m / (m / i));
ans += (getsum(j) - getsum(i - 1)) * (n / i) * (m / i);
}
ask[i].ans = ans;
} sort(ask + 1, ask + 1 + q, [](const query &a, const query &b) { return a.id < b.id; });
for (int i = 1; i <= q; i++) printf("%d\n", ask[i].ans & 2147483647);
return 0;
}

题目要求对2^31取模,别忘了自然溢出最后对2147483647取一下and

luogu3312 [SDOI2014]数表 (莫比乌斯反演+树状数组)的更多相关文章

  1. BZOJ 3259 [Sdoi2014]数表 (莫比乌斯反演 + 树状数组)

    3529: [Sdoi2014]数表 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 2321  Solved: 1187[Submit][Status ...

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

    [BZOJ3529][Sdoi2014]数表 Description 有一张N×m的数表,其第i行第j列(1 < =i < =礼,1 < =j < =m)的数值为能同时整除i和 ...

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

    3529: [Sdoi2014]数表 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 1399  Solved: 694[Submit][Status] ...

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

    题目大意:有一张$n*m$的数表,第$i$行第$j$列的数是同时能整除$i,j$的所有数之和,求数表内所有不大于A的数之和 先是看错题了...接着看对题了发现不会做了...刚了大半个下午无果 看了Po ...

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

    $ans=\sum_{i=1}^n\sum_{j=1}^n\sigma(gcd(i,j))$ 枚举gcd为d的所有数得到 $ans=\sum_{d<=n}\sigma(d)*g(d)$ $g(d ...

  6. BZOJ3529: [Sdoi2014]数表(莫比乌斯反演 树状数组)

    题意 题目链接 Sol 首先不考虑\(a\)的限制 我们要求的是 \[\sum_{i = 1}^n \sum_{j = 1}^m \sigma(gcd(i, j))\] 用常规的套路可以化到这个形式 ...

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

    题目大意: 有一张N×m的数表,其第i行第j列(1 < =i < =礼,1 < =j < =m)的数值为能同时整除i和j的所有自然数之和.给定a,计算数表中不大于a的数之和. ...

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

    Description 有一张N×m的数表,其第i行第j列(1 < =i < =礼,1 < =j < =m)的数值为 能同时整除i和j的所有自然数之和.给定a,计算数表中不大于 ...

  9. BZOJ_3529_[Sdoi2014]数表_莫比乌斯反演+树状数组

    Description 有一张 n×m 的数表,其第 i 行第 j 列(1 <= i <= n, 1 <= j <= m)的数值为 能同时整除 i 和 j 的所有自然数之和.给 ...

随机推荐

  1. DVWA平台v1.9-Brute Force

    Low: 随便输一下用户名,密码,test 点击Login 显示用户名或密码错误 在owasp-zap查看数据包 点击,就会转到这 右键,点击Fuzz 点击Remove删除默认的 选定参数变量值,点击 ...

  2. 下拉框改变事件:获取下拉框中当前选择的文本 SelectionChanged事件

    /// <summary> /// 下拉框改变事件:获取下拉框中当前选择的文本 /// </summary> /// <param name="sender&q ...

  3. delphi 从 TWebbrowse组件中获取图片

    在 delphi 中使用 TWebbrowse 组件,虽然效率不如用(idhttp之类)模拟操作效率高.但其难度低,上手快,简单粗暴有效. 从网上搜到的处理此问题的文章大多是 ctrl + c 复制到 ...

  4. 10-30SQLserver基础--(备份和还原、分离和附加数据库)、语句查询操作

    一.数据库是一个大容量的存储数据的仓库,为了保证数据完整性,防止一些数据的意外丢失等情况,需要对数据进行备份和还原. 备份数据不影响数据库的正常运行. 1.备份.还原数据库 首先对数据库进行备份,操作 ...

  5. C#调用带返回值的存储过程

    ()在SQL Server中建立如下的存储过程: set ANSI_NULLS ON set QUOTED_IDENTIFIER ON GO CREATE PROCEDURE [dbo].[GetNa ...

  6. 分步编译一个C语言文件

    一. 以下是C程序一般的编译过程: 从图中看到: 将编写的一个c程序(源代码 )转换成可以在硬件上运行的程序(可执行代码 ),需要进行编译阶段  和链接这两个阶段. 其中, 1.  编译阶段先通过“编 ...

  7. js语法和数据类型

    基础知识(Basics) JavaScript 的很多语法借鉴自 Java,但也受 Awk,Perl 和 Python 影响. JavaScript 是大小写敏感的,使用 Unicode 字符集. 在 ...

  8. sql基本查询语句练习

    student(S#,Sname,Sage,Ssex) 学生表       S#:学号: Sname:学生姓名:Sage:学生年龄:Ssex:学生性别 Course(C#,Cname,T#) 课程表 ...

  9. Android中无标题样式和全屏样式学习

    在进行UI设计时,我们经常需要将屏幕设置成无标题栏或者全屏.要实现起来也非常简单,主要有两种方法:配置xml文件和编写代码设置. 1.在xml文件中进行配置 在项目的清单文件AndroidManife ...

  10. day36-hibernate检索和优化 01-上次课内容回顾

    clear():直接清空一级缓存的所有对象.evict(Object obj):清空一个对象.flush():控制你的刷出的时机.refresh(Object obj);将你的数据查出来把一级缓存覆盖 ...