$ \color{#0066ff}{ 题目描述 }$

一天,olinr 在 luogu.org 刷题,一点提交,等了一分钟之后,又蛙又替。

olinr 发动了他的绝招,说:“为啥啊???”此时 leigehhh 拿着 6 个 map 走了过来,说:

“你这个维护一个破(pre)就行了啊” olinr 恍然大悟,问 GMPotlc,“琛哥你还有 D 吗我要

维护一个 D”。

olinr 从 GMPotlc 那里得到了一块 n*m 大小的 D,用来种植 xkj。

由于光照、二氧化碳浓度、温度等原因,olinr 得到的 D 有一个特性,对于第 i 行第 j

列种植的 xkj,一共有 lcm(i,j)个,并且营养程度为 gcd(i,j)。

olinr 希望将他的 D 的部分 xkj 出售给肯德基三人篮球赛举办方 KKF 用以在 NKFCP(全

国青少年肯德基三人篮球赛联赛)、NKFCWC(全国青少年肯德基三人篮球赛冬令营)、CKFC

(肯德基三人篮球赛中国国家队选拔赛)、IKFC(肯德基三人篮球赛全球赛)、NKFC(全国

青少年肯德基三人篮球赛)、APKFC(亚洲太平洋地区肯德基三人篮球赛)等赛事上提供服

务,KKF 为了保证 KFCers 的身心健康,只接受营养程度在[a,b]之间的 xkj,请你对于 olinr

的每次询问输出他能够出售的 xkj 数量。

\(\color{#0066ff}{输入格式}\)

第一行输入一个整数 q 代表 olinr 的询问数量

接下来 q 行每行 6 个整数 x1 x2 y1 y2 a b 表示 olinr 希望将横坐标在[x1, x2]范围并且纵

坐标在[y1, y2]范围并且营养程度在[a, b]范围的 xkj 出售。每次询问之间相互独立。

\(\color{#0066ff}{输出格式}\)

输出 q 行,每行 1 个数表示答案。由于出题人故意卡你所以请输出 mod998244353 结果

\(\color{#0066ff}{输入样例}\)

5
1 5 1 6 2 8
3 8 4 9 2 20
1 4 1 4 1 4
2 5 7 9 3 10
9 9 3 3 3 3

\(\color{#0066ff}{输出样例}\)

46
151
72
17
9

\(\color{#0066ff}{数据范围与提示}\)

对于 40%的数据,n,m,q<=1000;

对于 100%的数据,n,m<=\(10^5\) \(q<=10^4\)

我们保证每次询问数据 1<=x1<=x2<=n,1<=y1<=y2<=m,并且 1<=a<=b<=\(10^5\)。

提示:n 和 m 不会在输入中出现,但是保证满足数据范围

\(\color{#0066ff}{题解}\)

题目就是要求

\[\sum_{i=a}^b\sum_{j=c}^d[gcd(i,j)\in[l,r]]lcm(i,j)
\]

搞个前缀和

\[\sum_{i=a}^b\sum_{j=c}^d[gcd(i,j)\le r]lcm(i,j) -\sum_{i=a}^b\sum_{j=c}^d[gcd(i,j)\le l-1]lcm(i,j)
\]

对于每一个

\[\sum_{i=a}^b\sum_{j=c}^d[gcd(i,j)\le d]lcm(i,j)
\]

可以容斥一下

\[\sum_{i=1}^n\sum_{j=1}^m[gcd(i,j)\le p]\frac{i*j}{gcd(i,j)}
\]

枚举gcd

\[\sum_{d=1}^p\sum_{i=1}^n\sum_{j=1}^m[gcd(i,j)==d]\frac{i*j}{d}
\]

把d除上去

\[\sum_{d=1}^p\sum_{i=1}^{\lfloor\frac n d \rfloor}\sum_{j=1}^{\lfloor\frac m d \rfloor}[gcd(i,j)==1]i * j * d
\]

把d提到前面

\[\sum_{d=1}^pd\sum_{i=1}^{\lfloor\frac n d \rfloor}\sum_{j=1}^{\lfloor\frac m d \rfloor}[gcd(i,j)==1]i * j
\]

利用卷积代换

\[\sum_{d=1}^pd\sum_{i=1}^{\lfloor\frac n d \rfloor}\sum_{j=1}^{\lfloor\frac m d \rfloor}\sum_{k|gcd(i,j)}\mu(k)*i * j
\]

枚举约数,形成常见的形式

\[\sum_{d=1}^pd\sum_{k=1}^{min(\lfloor\frac n d \rfloor,\lfloor\frac m d \rfloor)}\mu(k)*k*k\sum_{i=1}^{\lfloor\frac{n}{kd} \rfloor}i\sum_{j=1}^{\lfloor\frac {m}{kd} \rfloor}j
\]

然而面对多组数据,还有1e5的数据范围,这肯定是不行的

于是,我们进行kd换T

枚举T

\[\sum_{T=1}^{min(n,m)}T\sum_{d|T}^{p}\mu(\frac T d)*\frac T d\sum_{i=1}^{\lfloor\frac{n}{T} \rfloor}i\sum_{j=1}^{\lfloor\frac {m}{T} \rfloor}j
\]

要注意,中间的不能预处理!! 有限制!!

考虑把询问拆开,存成两个询问,按p从小到大排序,维护一个d的单调指针,每次把\(\le p\)的k加进去(枚举倍数,用树状数组记录前缀和

然后直接整数分块\(O(m\sqrt nlogn)\)

#include<bits/stdc++.h>
#define LL long long
LL in() {
char ch; LL x = 0, f = 1;
while(!isdigit(ch = getchar()))(ch == '-') && (f = -f);
for(x = ch ^ 48; isdigit(ch = getchar()); x = (x << 1) + (x << 3) + (ch ^ 48));
return x * f;
}
const int mod = 998244353;
const int maxn = 1e5 + 100;
int pri[maxn], tot;
LL mu[maxn];
bool vis[maxn];
struct node {
LL x, xx, y, yy, lim, opt, id;
friend bool operator < (const node &a, const node &b) { return a.lim < b.lim; }
node(LL x = 0, LL xx = 0, LL y = 0, LL yy = 0, LL lim = 0, LL opt = 0, LL id = 0): x(x), xx(xx), y(y), yy(yy), lim(lim), opt(opt), id(id) {}
}e[maxn << 1];
struct Tree {
protected:
LL st[maxn];
int low(int x) { return x & (-x); }
public:
void add(int pos, LL k) { while(pos < maxn) (st[pos] += k) %= mod, pos += low(pos); }
LL query(int pos) { LL re = 0; while(pos) (re += st[pos]) %= mod, pos -= low(pos); return re; }
}s;
LL getsum(LL len) {
return ((len * (len + 1)) >> 1) % mod;
}
void predoit() {
mu[1] = 1;
for(int i = 2; i < maxn; i++) {
if(!vis[i]) pri[++tot] = i, mu[i] = -1;
for(int j = 1; j <= tot && i * pri[j] < maxn; j++) {
vis[i * pri[j]] = true;
if(i % pri[j] == 0) break;
else mu[i * pri[j]] = -mu[i];
}
}
}
LL work(LL n, LL m) {
LL ans = 0;
for(LL l = 1, r; l <= std::min(n, m); l = r + 1) {
r = std::min(n / (n / l), m / (m / l));
(ans += getsum(n / l) * getsum(m / l) % mod * (((s.query(r) - s.query(l - 1)) % mod) + mod) % mod) %= mod;
}
return ans;
} LL getans(LL x, LL y, LL xx, LL yy) {
return ((work(xx, yy) - work(x - 1, yy) - work(xx, y - 1) + work(x - 1, y - 1)) % mod + mod) % mod;
}
int main() {
freopen("plot.in", "r", stdin);
freopen("plot.out", "w", stdout);
predoit();
int num = 0, T = in();
for(int i = 1; i <= T; i++) {
LL x = in(), xx = in(), y = in(), yy = in(), a = in(), b = in();
e[++num] = node(x, xx, y, yy, a - 1, -1, i);
e[++num] = node(x, xx, y, yy, b, 1, i);
}
static LL ans[maxn];
std::sort(e + 1, e + num + 1);
LL now = 1;
for(int i = 1; i <= num; i++) {
while(now <= e[i].lim) {
for(LL i = now; i < maxn; i += now) s.add(i, (((i * mu[i / now] % mod * (i / now) % mod) + mod) % mod));
now++;
}
(ans[e[i].id] += ((e[i].opt * getans(e[i].x, e[i].y, e[i].xx, e[i].yy) % mod) + mod) % mod) %= mod;
}
for(int i = 1; i <= T; i++) printf("%lld\n", ans[i]);
return 0;
}

最新文章

  1. Introduction to Microsoft Dynamics 365 licensing
  2. php代码性能分析方法
  3. React Native 使用问题记录
  4. JavaScript继承与原型链
  5. Linux进程的前后台切换
  6. MongoDB学习(2)—Node.js与MongoDB的基本连接示例
  7. Odoo SSO 单点登录
  8. Python 决策树的构造
  9. IOS CopyPNGFile 异常问题解决
  10. System.OutOfMemoryException: 内存不足。(转)
  11. linux copy
  12. phpwind8.7升级9.0.1过程(二)8.7正式升级9.0
  13. ECMAScript 6 入门学习笔记(持续更新)
  14. Mac和Windows系统下Mysql数据库的导入导出
  15. RMQ(Range MinimumQuery)问题之ST算法
  16. dubbo协议下的单一长连接与多线程并发如何协同工作
  17. NHibernate 数据查询之Linq to NHibernate
  18. python 日期输出附带毫秒
  19. 空格填充器(alignBySpace)
  20. 挪过来的spring mvc 的入门 介绍

热门文章

  1. 并发模型(一)——Future模式
  2. EasyGui
  3. java游戏制作之水果忍者
  4. 如何用navicat premium 链接Oracel数据库
  5. 说说API的重放机制
  6. JAVA基础知识总结17(网络编程)
  7. Spring总结三:DI(依赖注入)
  8. vim 添加插件
  9. &lt;c:out&gt;标签中有一个escapeXml属性 如果为escapeXml=&quot;false&quot;,则将其中的html、xml解析出来。
  10. jQuery基础教程-第8章-001Adding new global functions