zoukankan      html  css  js  c++  java
  • 「HEOI2015」公约数数列 题解

    分块。

    首先查看询问。我们要求最小的 \(p\),使得 \(\gcd(a_0,a_1,\dots,a_p) \times \operatorname{xor}(a_0,a_1,\dots,a_p)=x\)(其中 \(\operatorname{xor}\) 为异或和)。下面我们从 \(1\) 开始标号。

    首先能够得到 \(\gcd\) 的一些性质。

    1. \(\gcd(\gcd(a_1,a_2,\dots,a_n),\gcd(b_1,b_2,\dots,b_m))=\gcd(a_1,a_2,\dots,a_n,b_1,b_2,\dots,b_m)\),所以两个块之间的 \(\gcd\) 可以合并;
    2. \(\gcd(a_1,a_2,\dots,a_p) \geq \gcd(a_1,a_2,\dots,a_{p+1})\),即新加入一个数的 \(\gcd\) 一定小于等于之前的 \(\gcd\)
    3. 对于前缀 \(\gcd\),每次发生改变,至少变到原来的 \(\dfrac{1}{2}\),即取值最多有 \(O(\log a_i)\) 个。

    好了有了这两个性质我们就有想法了。维护下面四个东西:

    • 块内 \(\operatorname{xor}\) 和;
    • 块内 \(\gcd\)
    • 对于每个位置,求出这个位置作为结尾的前缀异或和;
    • 每一块头尾两个数的前缀 \(\gcd\)。(这个可以直接通过第二个东西求出来)。

    对于修改,我们直接修改掉原来的元素,然后因为这个修改不会影响其他块,所以对于这个块我们暴力重构,时间复杂度 \(O(\sqrt n)\)

    对于查询,如果说这一块头尾两个数的前缀 \(\gcd\) 是相等的,说明这块内没有发生变化,所以可以直接在排好序的块内二分查找查询是否有解就行了。

    否则,暴力查询,遍历块内是否有解。因为不同的 \(\gcd\) 值最多有 \(O(\log a_i)\) 个,所以时间复杂度 \(O(\sqrt n \log ^2 n)\)

    总时间复杂度 \(O(q\sqrt n \log ^2n)\)

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    struct block{
    	LL val,pos;
    	block(){val=pos=0;}
    	block(LL V,LL P){val=V,pos=P;}
    	bool operator < (block another) const {return (val<another.val) || (val==another.val && pos<another.pos);}
    }s[100005];
    LL gcd(LL a,LL b){return !b?a:gcd(b,a%b);}
    LL n,a[100005],q,p,l[400],r[400],pos[100005],g[100005],x[100005];
    void replace(LL t)
    {
    	g[l[t]]=x[l[t]]=a[l[t]];
    	s[l[t]]=block(a[l[t]],l[t]);
    	for(LL i=l[t]+1;i<=r[t];++i)
    	{
    		g[i]=gcd(g[i-1],a[i]);
    		x[i]=x[i-1]^a[i];
    		s[i]=block(x[i],i);
    	}
    	sort(s+l[t],s+r[t]+1);
    }
    LL binarysearch(LL l,LL r,LL val)
    {
    	LL ans=l;
    	while(l<=r)
    	{
    		LL mid=(l+r)>>1;
    		if(s[mid].val>=val)	ans=mid,r=mid-1;
    		else	l=mid+1;
    	}
    	return ans;
    }
    LL query(LL u)
    {
    	LL ans=114514;
    	LL gd=a[1],xo=0;
    	for(LL i=1;i<=pos[n] && ans==114514;++i)
    	{
    		if(gcd(gd,g[r[i]])==gd)
    		{
    			if(u%gd==0)
    			{
    				LL p=(u/gd)^xo;
    				LL pos=binarysearch(l[i],r[i],p);
    				if(s[pos].val==p)	ans=s[pos].pos;
    			}
    			gd=gcd(gd,g[r[i]]);
    			xo^=x[r[i]];
    		}
    		else
    		{
    			for(LL j=l[i];j<=r[i];++j)
    			{
    				gd=gcd(gd,a[j]);
    				xo^=a[j];
    				if(gd*xo==u)
    				{
    					ans=j;
    					break;
    				}
    			}
    		}
    	}
    	return ans;
    }
    int main(){
    	scanf("%lld",&n);
    	p=sqrt(n);
    	for(LL i=1;i<=n;++i)
    	{
    		scanf("%lld",&a[i]);
    		pos[i]=(i-1)/p+1;
    		if(!l[pos[i]])	l[pos[i]]=i;
    		r[pos[i]]=i;
    	}
    	for(LL i=1;i<=pos[n];++i)	replace(i);
    	LL q;
    	scanf("%lld",&q);
    	while(q-->0)
    	{
    		char o[8];
    		scanf("%s",o);
    		if(o[0]=='M')
    		{
    			LL where,val;
    			scanf("%lld %lld",&where,&val);
    			++where;
    			a[where]=val;
    			replace(pos[where]);
    		}
    		else
    		{
    			LL val;
    			scanf("%lld",&val);
    			LL output=query(val);
    			if(output==114514)	puts("no");
    			else	printf("%lld\n",output-1);
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    Stream processing with Apache Flink and Minio
    Replicated Ship 本地 kubernetes 环境试用
    replicatedhq-ship 基于Kustomize 项目的快速kubernetes 应用部署工具
    kustomize 模版自由的配置&&自定义kubernetes工具
    hasura graphql-engine v1.0.0-alpha30 remote schema stitch 试用
    Modern Data Lake with Minio : Part 2
    Modern Data Lake with Minio : Part 1
    使用rclone 进行minio 文件同步
    hasura graphql-engine v1.0.0-alpha30 功能试用
    hasura graphql-engine v1.0.0-alpha30 版本新功能介绍
  • 原文地址:https://www.cnblogs.com/amagaisite/p/13406215.html
Copyright © 2011-2022 走看看