ZOJ 3940 Modulo Query(YY+二分)
Modulo Query
Time Limit: 2 Seconds Memory Limit: 65536 KB
One day, Peter came across a function which looks like:
- F(1, X) = X mod A1.
- F(i, X) = F(i - 1, X) mod Ai, 2 ≤ i ≤ N.
Where A is an integer array of length N, X is a non-negative integer no greater than M.
Peter wants to know the number of solutions for equation F(N, X) = Y, where Y is a given number.
Input
There are multiple test cases. The first line of input contains an integer T, indicating the number of test cases. For each test case:
The first line contains two integers N and M (2 ≤ N ≤ 105, 0 ≤ M ≤ 109).
The second line contains N integers: A1, A2, ..., AN (1 ≤ Ai ≤ 109).
The third line contains an integer Q (1 ≤ Q ≤ 105) - the number of queries. Each of the following Q lines contains an integer Yi (0 ≤ Yi ≤ 109), which means Peter wants to know the number of solutions for equation F(N, X) = Yi.
Output
For each test cases, output an integer S = (1 ⋅ Z1 + 2 ⋅ Z2 + ... + Q ⋅ ZQ) mod (109 + 7), where Zi is the answer for the i-th query.
Sample Input
1
3 5
3 2 4
5
0
1
2
3
4
Sample Output
8
Hint
The answer for each query is: 4, 2, 0, 0, 0.
题目链接:ZOJ 3940
题意:给出N个数Ai和M,又给Q个询问,每一个询问都是求[0,M]中求是否存在X使得X%A1%A2%A3%......%An=Yi,输出符合有几个这种整数X。
可以发现任何情况下对连续的数取模除非当前值比上一个取模值小,否则直接跳过即可,当然最重要的不是这里,而是如何把题目转换一下,每一次问[0,M]中符合题意的X个数,那么我们可以把[0,M]区间分割为无数个被取模后的小区间,若计这些小区间的贡献均为1,则覆盖在点Yi的情况就是询问Yi的答案,怎么分割呢,当然是用题目给的A数组分割,顺序地输入数组,这里就可以用到上面讲到的取模的技巧来减少分割的次数,分割之后做一遍前缀或后缀和(比如小区间0-1与0-2,0-2显然是包括0-1的,因此是前缀或后缀和关系,两种不同的和只会影响统计时候的加减法问题不会影响答案)。然后询问的时候二分到第一个大于Yi的区间,假设你输入的是3,二分出来的位置是pos,pos对应的子区间为0-4,答案就是从pos~end的贡献和。因为在pos之前只会产生小于3的数,不可能出现3的情况,只有从至少%4开始,才会出现3
代码:
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
typedef pair<int, int> pii;
typedef long long LL;
const int N = 1e5 + 7;
const LL MOD = 1e9 + 7;
int A[N];
map<int, int>pos;
pii prefix[N << 2]; inline int getpos(int l, int r, int key)
{
int ans = -1;
while (l <= r)
{
int mid = (l + r) >> 1;
if (prefix[mid].first > key)
{
ans = mid;
r = mid - 1;
}
else
l = mid + 1;
}
return ans;
}
int main(void)
{
int tcase, n, m, i, q;
scanf("%d", &tcase);
while (tcase--)
{
int Min = INF;
pos.clear();
scanf("%d%d", &n, &m);
pos[m + 1] = 1;
prefix[0] = {0, 0};
for (i = 1; i <= n; ++i)
{
scanf("%d", &A[i]);
if (A[i] < Min)
Min = A[i];
while (1)
{
auto it = pos.upper_bound(A[i]);
if (it == pos.end())
break;
int olde = it->first;
int oldcnt = it->second;
pos[A[i]] += olde / A[i] * oldcnt;
if (olde % A[i] != 0)
pos[olde % A[i]] += oldcnt;
pos.erase(it);
}
}
auto it = pos.begin();
int sz = 0;
while (it != pos.end())
{
++sz;
prefix[sz].second = prefix[sz - 1].second + it->second;
prefix[sz].first = it->first;
++it;
}
scanf("%d", &q);
LL ans = 0LL;
for (i = 1; i <= q; ++i)
{
LL curans;
int x;
scanf("%d", &x);
if (x >= Min)
curans = 0LL;
else
{
int l = getpos(1, sz, x);
if (~l)
curans = prefix[sz].second - prefix[l - 1].second;
else
curans = 0LL;
}
if (curans)
{
ans = ans + (LL)i * curans % MOD;
if (ans > MOD)
ans %= MOD;
}
}
printf("%lld\n", ans);
}
return 0;
}
ZOJ 3940 Modulo Query(YY+二分)的更多相关文章
- ZOJ 3940 Modulo Query
0--M对某个数字取模,相当于把0--M区间进行切割,每次暴力切割一下.结果的算的时候二分一下即可... 看了官方题解才会... #include<cstdio> #include< ...
- ZOJ 3940 Modulo Query (2016年浙江省赛E题,区间折叠 + map运用)
题目链接 2016 ZJCPC Problem E 考虑一个开区间$[0, x)$对$a_{i}$取模的过程. $[0, x)$中小于$a_{i}$的部分不变,大于等于$a_{i}$的部分被切下来变 ...
- ZOJ 3911 Prime Query ZOJ Monthly, October 2015 - I
Prime Query Time Limit: 1 Second Memory Limit: 196608 KB You are given a simple task. Given a s ...
- ZOJ 3911 Prime Query(线段树)
Prime Query Time Limit: 1 Second Memory Limit: 196608 KB You are given a simple task. Given a s ...
- ZOJ 4062 - Plants vs. Zombies - [二分+贪心][2018 ACM-ICPC Asia Qingdao Regional Problem E]
题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=4062 题意: 现在在一条 $x$ 轴上玩植物大战僵尸,有 $n$ ...
- 2018 青岛ICPC区域赛E ZOJ 4062 Plants vs. Zombie(二分答案)
Plants vs. Zombies Time Limit: 2 Seconds Memory Limit: 65536 KB BaoBao and DreamGrid are playin ...
- zoj 2362 Beloved Sons【二分匹配】
题目:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2361 来源:http://acm.hust.edu.cn/vjudg ...
- ZOJ 5638——Prime Query——————【线段树区间更新,区间查询,单点更新】
Prime Query Time Limit: 1 Second Memory Limit: 196608 KB You are given a simple task. Given a s ...
- ZOJ 2112 Dynamic Rankings(二分,树套树)
动态区间询问kth,单点修改. 区间用线段树分解,线段树上每条线段存一颗平衡树. 不能直接得到kth,但是利用val和比val小的个数之间的单调性,二分值.log^3N. 修改则是一次logN*log ...
随机推荐
- SSH框架快速搭建(Maven)
1.新建Maven项目ssh 2.pom.xml <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi=& ...
- javascript同步和异步的区别与实现方式
javascript语言是单线程机制.所谓单线程就是按次序执行,执行完一个任务再执行下一个. 对于浏览器来说,也就是无法在渲染页面的同时执行代码. 单线程机制的优点在于实现起来较为简单,运行环境相对简 ...
- Java设计模式学习——设计原则
第一章 设计原则 1.开闭原则 一个软件实体,像类,模块,函数应该对扩展开放,对修改关闭 在设计的时候,要时刻考虑,让这个类尽量的好,写好了就不要去修改.如果有新的需求来,在增加一个类就完事了,原来的 ...
- ES6 Proxy拦截器详解
Proxy 拦截器 如有错误,麻烦指正,共同学习 Proxy的原意是"拦截",可以理解为对目标对象的访问和操作之前进行一次拦截.提供了这种机制,所以可以对目标对象进行修改和过滤的操 ...
- 4396: [Usaco2015 dec]High Card Wins
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 275 Solved: 175[Submit][Status][Discuss] Descriptio ...
- AIDE
安装 yum install aide 修改配置文件 vim /etc/aide.conf (指定对哪些文件进行检测) /test/chameleon R /bin/ps R+a /usr/bin/c ...
- sql 参数化查询
在初次接触sql时,笔者使用的是通过字符串拼接的方法来进行sql查询,但这种方法有很多弊端 其中最为明显的便是导致了sql注入. 通过特殊字符的书写,可以使得原本正常的语句在sql数据库里可编译, ...
- 让你提高效率的 Linux 技巧
想要在 Linux 命令行工作中提高效率,你需要使用一些技巧. 巧妙的 Linux 命令行技巧能让你节省时间.避免出错,还能让你记住和复用各种复杂的命令,专注在需要做的事情本身,而不是你要怎么做.以下 ...
- java 调用第三方系统时的连接代码-记录
前言:该文章主要是总结我在实际工作中遇到的问题,在调取第三方系统的时候出现的问题,算自己的总结.各位博友如果有什么建议或意见欢迎留言指正. 先将准备传入参数 再与第三方系统建立连接 再第三方系统处理后 ...
- Python入门第一课——Python的起源、发展与前景!
我们在做任何一件事情之前,我们都会通过各种渠道去搜集事情的信息,了解事情的来龙去脉,学习一门编程语言也是如此,只有知根知底,我们才能有明确的方向和目标,以及底气去完成这件事情,今天我带大家来看看Pyt ...