博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
gcd的性质+分块 Bzoj 4028
阅读量:6344 次
发布时间:2019-06-22

本文共 4472 字,大约阅读时间需要 14 分钟。

4028: [HEOI2015]公约数数列

Time Limit: 10 Sec  Memory Limit: 256 MB
Submit: 865  Solved: 311
[][][]

Description

设计一个数据结构. 给定一个正整数数列 a_0, a_1, ..., a_{n - 1},你需要支持以下两种操作:

1. MODIFY id x: 将 a_{id} 修改为 x.
2. QUERY x: 求最小的整数 p (0 <= p < n),使得 gcd(a_0, a_1, ..., a_p) * XOR(a_0, a_1, ..., a_p) = x. 其中 XOR(a_0, a_1, ..., a_p) 代表 a_0, a_1, ..., a_p 的异或和,gcd表示最大公约数。

Input

 输入数据的第一行包含一个正整数 n.

接下来一行包含 n 个正整数 a_0, a_1, ..., a_{n - 1}.
之后一行包含一个正整数 q,表示询问的个数。
之后 q 行,每行包含一个询问。格式如题目中所述。

Output

对于每个 QUERY 询问,在单独的一行中输出结果。如果不存在这样的 p,输出 no.

Sample Input

10
1353600 5821200 10752000 1670400 3729600 6844320 12544000 117600 59400 640
10
MODIFY 7 20321280
QUERY 162343680
QUERY 1832232960000
MODIFY 0 92160
QUERY 1234567
QUERY 3989856000
QUERY 833018560
MODIFY 3 8600
MODIFY 5 5306112
QUERY 148900352

Sample Output

6
0
no
2
8
8

HINT

 

 对于 100% 的数据,n <= 100000,q <= 10000,a_i <= 10^9 (0 <= i < n),QUERY x 中的 x <= 10^18,MODIFY id x 中的 0 <= id < n,1 <= x <= 10^9.

 

思路:

因为我们知道,gcd每次必然是/2的,所以gcd最多就只要log个,然后呢,我们对每个块都分块,并且记录每个块的gcd[i]和xor[i],分别表示gcd(1~i)和xor(1~i),

①如果是单点修改的话,就暴力更新一下目前的块即可,所以暴力更新的复杂度为n^0.5

②如说是查询的话,我们就暴力每个块,对于目前这个块。 

定义pregcd表示目前这个块之前所有的数字的gcd,prexor为目前这个块之前所有的数字的xor。然后,如果这个块中,他的gcd[r[i]]和pregcd求gcd以后没有发生变化,那么就表示可能存在xor[j]^prexor * (pregcd和gcd[r[i]]的gcd) = val。那么我们就二分去看看存不存在这个xor[j],如果存在,就从头开始暴力,找到最小的。当然,这个二分的话可以用set来维护,只需要set.count()就可以查询了。所以这里的复杂度为sqrt(n) * log(sqrt(n))

如果gcd发生了变化那么我们就暴力去查询即可,所以这里的复杂度为sqrt(n).

因为gcd最多不会超过log个,所以上面查询+修改的最大复杂度为q*sqrt(n)*log(sqrt(n))

//看看会不会爆int!数组会不会少了一维!//取物问题一定要小心先手胜利的条件#include 
using namespace std;#pragma comment(linker,"/STACK:102400000,102400000")#define LL long long#define ALL(a) a.begin(), a.end()#define pb push_back#define mk make_pair#define fi first#define se second#define haha printf("haha\n")/*首先,我们对所有的东西进行分块,然后我们对每个区间进行处理,分别得到这个区间的gcd和xor。①然后如果前面的区间到这个块以后的gcd如果发生了改变,那么,我们就暴力这个块,复杂度为sqrt(n)②如果前面的区间到这个块以后gcd没有发生改变,那么我们就二分这个块,二分的证明如下:假定lastxor是该区间之前的xor值,lastgcd是该区间之前的gcd的值,假定我们要寻找的xor[j]是在这个块中那么xor[j]^lastxor * lastgcd = k,转化以后为xor[j] = k/lastgcd ^ lastxor,所以我们只要二分这个块就好了因此这里的复杂度为logn因为gcd一共就只有logn个,所以复杂度最坏为sqrt(n) * logn个*/const int maxn = 1e6 + 5;LL a[maxn], Xor[maxn], gcd[maxn];int l[maxn], r[maxn], block, num, belong[maxn];int n, q;set
S[maxn];LL get_gcd(LL a, LL b){ return b == 0 ? a : get_gcd(b, a % b);}void build(){ block = sqrt(n); num = n / block; if (n % block) num++; for (int i = 1; i <= num; i++) l[i] = (i - 1) * block + 1, r[i] = i * block; r[num] = n; for (int i = 1; i <= n; i++){ belong[i] = (i - 1) / block + 1; }}void update(int p){ S[p].clear(); gcd[l[p]] = a[l[p]], Xor[l[p]] = a[l[p]]; S[p].insert(Xor[l[p]]); for (int i = l[p] + 1; i <= r[p]; i++){ gcd[i] = get_gcd(gcd[i - 1], a[i]); Xor[i] = Xor[i - 1] ^ a[i]; S[p].insert(Xor[i]); }}void query(LL val){ LL prexor, pregcd; for (int i = 1; i <= r[1]; i++){ if (gcd[i] * Xor[i] == val){ printf("%d\n", i-1); return ; } } prexor = Xor[r[1]], pregcd = gcd[r[1]]; for (int i = 2; i <= num; i++){ LL nowgcd = get_gcd(pregcd, gcd[r[i]]); if (nowgcd == pregcd){
///xor[i] ^ prexor * nowgcd = val LL tmp = val / nowgcd ^ prexor; if (val % nowgcd == 0 && S[i].count(tmp)){ for (int j = l[i]; j <= r[i]; j++){ if (Xor[j] == tmp){ printf("%d\n", j - 1); return ; } } } } else { for (int j = l[i]; j <= r[i]; j++){ nowgcd = get_gcd(gcd[j], pregcd); LL tmp = val / nowgcd ^ prexor; if (val % nowgcd == 0 && Xor[j] == tmp){ printf("%d\n", j - 1); return; } } } pregcd = get_gcd(pregcd, gcd[r[i]]); prexor = prexor ^ Xor[r[i]]; } printf("no\n");}int main(){ cin >> n; for (int i = 1; i <= n; i++){ scanf("%lld", a + i); } build(); for (int i = 1; i <= num; i++) update(i); scanf("%d", &q); char ch[20]; for (int i = 1; i <= q; i++){ scanf("%s", ch); if (ch[0] == 'M'){ int p; LL val; scanf("%d%lld", &p, &val); a[++p] = val; update(belong[p]); } else{ LL val; scanf("%lld", &val); query(val); } } return 0;}
View Code

 

转载于:https://www.cnblogs.com/heimao5027/p/6539543.html

你可能感兴趣的文章
Oracle 客户端安装
查看>>
洛谷 P1744(迪杰斯特拉)
查看>>
win7 配置IIS + php 环境
查看>>
[UML]UML系列——用例图中的各种关系(include、extend)
查看>>
若要调试此模块,请将其项目生成配置更改为“调试”模式。若要取消显示此消息,请禁用“启动时若没有用户代码则发出警告”调试器选项。...
查看>>
08.Python网络爬虫之图片懒加载技术、selenium和PhantomJS
查看>>
java_socket套接字网络编程_实现多线程聊天
查看>>
SpringMVC + Spring + MyBatis 学习笔记:在类和方法上都使用RequestMapping如何访问
查看>>
[转载]使用RoboCopy 命令
查看>>
清楚浮动的应用
查看>>
spring cloud学习(五) 配置中心
查看>>
Oracle误删除表空间的恢复
查看>>
C++的继承与多态
查看>>
CSS3 Border-image
查看>>
洛谷P4769 冒泡排序
查看>>
固定思维的可怕(转)
查看>>
pimple idiom C++
查看>>
关于Session为null的问题。。。
查看>>
新的开始,一切归零
查看>>
tomcat 详解 catalina.home和catalina.base
查看>>