LOJ6231. GCD & XOR

很好的题目。

首先,\(\gcd\) 有个很好的性质:

对于一列数组,从左往右取前缀 \(\gcd\),不同的值最多只有 \(\log w\) 种。

我的yy证明:

对于 a[1],它最多为 \(\log w\) 个质因子相乘(全取2),而每向后扫一个数,质因子数要么不变,要么减一,所以至多有 \(\log w\) 个,所以有很多 \(\gcd\) 是相同的。

而且 \(\gcd\) 是满足结合律的,所以很好预处理。

所以我们可以倍增预处理 \(\gcd\) ,然后开始扫,然后倍增跳,然后在找符合的 \(\text{xor}\) 值。

时间复杂度:\(O(n\log^2 n)\)

PS:map的小用法:map很适合这种查找的工作

插入 m.insert(make_pair()) \(O(\log n)\)

或直接用数组复制 m[key]=value... \(O(\log n)\)

然后每次调用 m[key] 时,若不存在则会新建一个二元组 (key,zero),本题中就是这样使用的。(zero 是一个广义的零值)。

然后删除 m.erase(it) 或 m.erase(make_pair()) \(O(\log n)\)

迭代器:用法同 set

empty,clear,size,begin,end同set \(O(1)\)

find(key):查找 key 值为 x 的二元组,若不存在则返回 m.end() \(O(\log n)\)

然后对于 map 里的每一个元素 x,x->first 表示 key 值,x->second 表示 value。

当然 map 里也是可以用 lower_bound(key) 返回的是 map 里的一个元素。

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=1e5+7;
template <class I>
inline void read(I &x){
    int f=1;
    char c;
    for(c=getchar();c<'0'||c>'9';c=getchar()) if(c=='-') f=-1;
    for(x=0;c>='0'&&c<='9';x=(x<<3)+(x<<1)+(c&15),c=getchar());
    x*=f;
}
int n;
ll a[N],f[N][19],K,jc[19],xr[N];
ll gcd(ll a,ll b){
	return b?gcd(b,a%b):a;
}
map <ll,vector<int> > mp;
map <ll,vector<int> >::iterator it;
vector <int>::iterator vit;
inline void init(){
	jc[0]=1;
	for(int i=1;i<19;i++) jc[i]=jc[i-1]<<1;
	for(int i=1;i<=n;i++) f[i][0]=a[i];
	for(int k=1;k<19;k++)
		for(int i=1;i+jc[k]-1<=n;i++)
			f[i][k]=gcd(f[i][k-1],f[i+jc[k-1]][k-1]);
	for(int i=1;i<=n;i++) 
		xr[i]=xr[i-1]^a[i],mp[xr[i]].push_back(i);
}
int main(){
	//freopen("sequence.in","r",stdin);
	//freopen("sequence.out","w",stdout);
	read(n);
	for(int i=1;i<=n;i++)
		read(a[i]);
	read(K);
	init();
	for(int l=1;l<=n;l++){
		ll gd=a[l];
		for(int i=l;i<=n;i++){
			gd=gcd(a[i],gd);
			int r=i;
			for(int k=18;k>=0;k--){
				if(r+jc[k]-1<=n&&(f[r][k]%gd==0)) r+=jc[k]-1;
			}
			if(K%gd) {
				i=r;
				continue;
			}
			it=mp.find((K/gd)^xr[l-1]);
			if(it==mp.end()) {
				i=r;
				continue;}
			vit=lower_bound((it->second).begin(),(it->second).end(),l);
			if(vit==(it->second).end()||*vit>r){
				i=r;
				continue;
			}
			printf("%d %d\n",l,*vit);
			return 0;
		}
	}
	puts("no solution");
	return 0;
}

posted @ 2019-10-18 17:18  天才美少女雪乃  阅读(142)  评论(0编辑  收藏  举报