4028: [HEOI2015]公约数数列

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

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 <bits/stdc++.h>
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 + ;
LL a[maxn], Xor[maxn], gcd[maxn];
int l[maxn], r[maxn], block, num, belong[maxn];
int n, q;
set<LL> S[maxn]; LL get_gcd(LL a, LL b){
return b == ? a : get_gcd(b, a % b);
} void build(){
block = sqrt(n); num = n / block;
if (n % block) num++;
for (int i = ; i <= num; i++)
l[i] = (i - ) * block + , r[i] = i * block;
r[num] = n;
for (int i = ; i <= n; i++){
belong[i] = (i - ) / block + ;
}
} 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] + ; i <= r[p]; i++){
gcd[i] = get_gcd(gcd[i - ], a[i]);
Xor[i] = Xor[i - ] ^ a[i];
S[p].insert(Xor[i]);
}
} void query(LL val){
LL prexor, pregcd;
for (int i = ; i <= r[]; i++){
if (gcd[i] * Xor[i] == val){
printf("%d\n", i-); return ;
}
}
prexor = Xor[r[]], pregcd = gcd[r[]];
for (int i = ; 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 == && S[i].count(tmp)){
for (int j = l[i]; j <= r[i]; j++){
if (Xor[j] == tmp){
printf("%d\n", j - ); 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 == && Xor[j] == tmp){
printf("%d\n", j - ); return;
}
}
}
pregcd = get_gcd(pregcd, gcd[r[i]]);
prexor = prexor ^ Xor[r[i]];
}
printf("no\n");
} int main(){
cin >> n;
for (int i = ; i <= n; i++){
scanf("%lld", a + i);
}
build();
for (int i = ; i <= num; i++)
update(i);
scanf("%d", &q);
char ch[];
for (int i = ; i <= q; i++){
scanf("%s", ch);
if (ch[] == '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 ;
}

gcd的性质+分块 Bzoj 4028的更多相关文章

  1. UVA 1642 Magical GCD(gcd的性质,递推)

    分析:对于区间[i,j],枚举j. 固定j以后,剩下的要比较M_gcd(k,j) = gcd(ak,...,aj)*(j-k+1)的大小, i≤k≤j. 此时M_gcd(k,j)可以看成一个二元组(g ...

  2. 洛谷 P5502 - [JSOI2015]最大公约数(区间 gcd 的性质+分治)

    洛谷题面传送门 学校模拟赛的某道题让我联想到了这道题-- 先讲一下我的野鸡做法. 首先考虑分治,对于左右端点都在 \([L,R]\) 中的区间我们将其分成三类:完全包含于 \([L,mid]\) 的区 ...

  3. BZOJ 4028: [HEOI2015]公约数数列 【分块 + 前缀GCD】

    任意门:https://www.lydsy.com/JudgeOnline/problem.php?id=4028 4028: [HEOI2015]公约数数列 Time Limit: 10 Sec   ...

  4. BZOJ 4028: [HEOI2015]公约数数列 分块

    4028: [HEOI2015]公约数数列 题目连接: http://www.lydsy.com/JudgeOnline/problem.php?id=4028 Description 设计一个数据结 ...

  5. 【BZOJ 2820】 YY的GCD (莫比乌斯+分块)

    YY的GCD   Description 神犇YY虐完数论后给傻×kAc出了一题 给定N, M,求1<=x<=N, 1<=y<=M且gcd(x, y)为质数的(x, y)有多少 ...

  6. BZOJ 4028 分块

    zrt当年是怎么想到的--. 思路: 考虑把序列分块 对于每块 存xor[i] 表示从本块开头到i的前缀异或和 把它扔进set里 存gcd[i]表示从本块开头到i的前缀gcd. 如果这一块的GCD和整 ...

  7. Bzoj-2820 YY的GCD Mobius反演,分块

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2820 题意:多次询问,求1<=x<=N, 1<=y<=M且gcd( ...

  8. 主席树||可持久化线段树+离散化 || 莫队+分块 ||BZOJ 3585: mex || Luogu P4137 Rmq Problem / mex

    题面:Rmq Problem / mex 题解: 先离散化,然后插一堆空白,大体就是如果(对于以a.data<b.data排序后的A)A[i-1].data+1!=A[i].data,则插一个空 ...

  9. bzoj 4028 : [HEOI2015]公约数数列

    之前看了好几次都没什么思路,今天下定决心把这题切了. 观察到$0-x$的gcd最多变化log次,因为它每次变化一定至少要去掉一个质因子,所以我们可以枚举gcd. 因为数据范围比较小,所以想到了分块. ...

随机推荐

  1. 【Alpha】阶段第一次Scrum Meeting

    [Alpha]阶段第一次Scrum Meeting 工作情况 团队成员 今日已完成任务 明日待完成任务 刘峻辰 后端接口开发 测试接口,修正bug 赵智源 撰写测试方案书 部署实际任务和编写测试样例 ...

  2. HDU 5187 zhx's contest 快速幂,快速加

    题目链接: hdu: http://acm.hdu.edu.cn/showproblem.php?pid=5187 bc(中文): http://bestcoder.hdu.edu.cn/contes ...

  3. git向github提交时不输入账号密码

    缘由:每次向github提交代码时都要输入用户名密码,太麻烦了,影响效率 解决方案: 方案一: 在你的用户目录下新建一个文本文件.git-credentials Windows:C:/Users/us ...

  4. Qt容器类汇总说明

    版权声明:若无来源注明,Techie亮博客文章均为原创. 转载请以链接形式标明本文标题和地址: 本文标题:Qt容器类汇总说明     本文地址:http://techieliang.com/2017/ ...

  5. PAT 甲级 1063 Set Similarity

    https://pintia.cn/problem-sets/994805342720868352/problems/994805409175420928 Given two sets of inte ...

  6. 自己编写 Oracle 分页函数

    CREATE OR REPLACE PACKAGE PACK_PAGINATION AS PAGESIZE CONSTANT ; TYPE TYRECORD_EMP IS RECORD( EMPNO ...

  7. Node.js系列——(2)发起get/post请求

    服务器与浏览器的交互主要方式有get/post请求. 下面,我们来看一下node.js发起get/post请求. 1.get 由于get请求的参数在url后面,所以相对比较简单.node.js中的ur ...

  8. 两个float 怎么比较大小

    转自:http://blog.csdn.net/mydriverc2/article/details/49888947 float 类型不能比较相等或不等,但可以比较>,<,>=,& ...

  9. HDU——1788 Chinese remainder theorem again

    再来一发水体,是为了照应上一发水题. 再次也特别说明一下,白书上的中国剩余定理的模板不靠谱. 老子刚刚用柏树上的模板交上去,简直wa出翔啊. 下面隆重推荐安叔版同余方程组的求解方法. 反正这个版本十分 ...

  10. bzoj2699 更新

    题意 对于一个数列A[1..N],一种寻找最大值的方法是:依次枚举A[2]到A[N],如果A[i]比当前的A[1]值要大,那么就令A[1]=A[i],最后A[1]为所求最大值.假设所有数都在范围[1, ...