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. struts-resultType属性

    1.默认dispatcher:forward方式,服务器端跳转 2.redirect:客户端跳转 3.chain:Action转发,forward方式,服务器端跳转action 4.redirectA ...

  2. 关于 Oracle Preinstallation RPM

    About the Oracle Preinstallation RPM 来源 https://docs.oracle.com/en/database/oracle/oracle-database/1 ...

  3. MVC 中创建自己的异常处理

    1.新建类一个类继承 HandleErrorAttribute 类把异常书写到队列中 public class MyExceptionAttribute: HandleErrorAttribute { ...

  4. C#中的静态常量(const)和动态常量(static和readonly)用法和区别

    C#中有两种常量类型,分别为readonly(运行时常量)与const(编译时常量),本文将就这两种类型的不同特性进行比较并说明各自的适用场景.工作原理 readonly为运行时常量,程序运行时进行赋 ...

  5. 【Quartz.Net】.net 下使用Quartz.Net

    Quartz.net是作业调度框架 1. 项目中添加quartz.net的引用(这里使用nuget管理) 新建一个类TimingJob,该类主要用于实现任务逻辑   using Quartz; usi ...

  6. HDU4787_GRE Words Revenge

    这个题目做得泪牛满面. 题目为给你若干串,有的表示添加一个串,有的表示询问一个串有多少个字串为前面出现过的串. 题目一看就知道肯定是AC自动机(不过后缀自动机也是可以的) 但是细想就会发现AC自动机好 ...

  7. hdu6415 Rikka with Nash Equilibrium (DP)

    题目链接 Problem Description Nash Equilibrium is an important concept in game theory. Rikka and Yuta are ...

  8. 51nod-1222-最小公倍数计数

    题意 给到 \(a,b\) ,求 \[ \sum _{i=a}^b\sum _x\sum _y[x\le y][\text{lcm}(x,y)=i] \] 即最小公倍数在 \([a,b]\) 中的有序 ...

  9. 用CSS实现3D 滚动的立方体

    用css3写3D立方体用到的属性不多,就那么几个:perspective,transform-style,以及transform. 目前来说能完美支持3D的浏览器有chrome.safari,火狐也支 ...

  10. Eve-NG-Toolkit

    Eve-NG-Toolkit 来源 http://www.emulatedlab.com/archives/694 参考 http://eve-ng.cn/doku.php   http://foru ...