zoukankan      html  css  js  c++  java
  • CF475D:CGCDSSQ

    浅谈(RMQ)https://www.cnblogs.com/AKMer/p/10128219.html

    题目传送门:https://codeforces.com/problemset/problem/475/D

    我们考虑当(l)固定之后,(r)在某个区间内的(gcd)是一样的,而且这样的区间只有(log),因为(gcd)改变的话至少会除以二。所以我们就可以用(st)表存(gcd),然后(log^2)的去往后跳,统计出一个一个这样的区间,最后离线处理所有的询问即可。

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

    空间复杂度:(O(nlogn))

    代码如下:

    #include <cstdio>
    using namespace std;
    typedef long long ll;
    
    const int maxn=1e5+5,pps=1e7+7;
    
    int n,m;
    int f[18][maxn];
    int a[maxn],Log[maxn];
    
    int read() {
    	int x=0,f=1;char ch=getchar();
    	for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
    	for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
    	return x*f;
    }
    
    struct HASH {
    	int tot;
    	int head[pps];
    	ll sum[maxn*20];
    	int nxt[maxn*20],g[maxn*20];
       
    
    	void ins(int v,int cnt) {
    		int tmp=v%pps;
    		for(int i=head[tmp];i;i=nxt[i])
    			if(g[i]==v) {sum[i]+=cnt;return;}
    		sum[++tot]=cnt,g[tot]=v,nxt[tot]=head[tmp],head[tmp]=tot;
    	}
    
    	ll find(int v) {
    		int tmp=v%pps;
    		for(int i=head[tmp];i;i=nxt[i])
    			if(g[i]==v)return sum[i];
    		return 0;
    	}
    }H;
    
    int gcd(int a,int b) {
    	while(b) {
    		int tmp=b;
    		b=a%b;a=tmp;
    	}
    	return a;
    }
    
    int find(int st,int GCD) {
    	for(int i=Log[n-st+1];i;i--)
    		if(f[i][st]&&f[i][st]%GCD==0)
    			st=st+(1<<i)-1;
    	return st+1;
    }
    
    void make_ans() {
    	Log[0]=-1;
    	for(int i=1;i<=n;i++)
    		Log[i]=Log[i>>1]+1;
    	for(int i=1;i<=17;i++)
    		for(int j=1;j+(1<<i)-1<=n;j++)
    			f[i][j]=gcd(f[i-1][j],f[i-1][j+(1<<(i-1))]);
    	for(int i=1;i<=n;i++) {
    		int pos=i,GCD=a[i];
    		while(pos<=n) {
    			int newpos=find(pos,GCD);
    			H.ins(GCD,newpos-pos);
    			pos=newpos,GCD=gcd(GCD,a[newpos]);
    		}
    	}
    }
    
    int main() {
    	n=read();
    	for(int i=1;i<=n;i++)
    		f[0][i]=a[i]=read();
    	make_ans(),m=read();
    	for(int i=1;i<=m;i++) {
    		int x=read();
    		printf("%lld
    ",H.find(x));
    	}
    	return 0;
    }
    
  • 相关阅读:
    勿忘心安
    设△ABC的内角A,B,C,所对的边分别为a,b,c,且acosB-bcosA=3/5c,则tan(A-B)的最大值为
    P1011 车站
    第一天
    P1134 阶乘问题
    P3152 正整数序列
    某数论
    DO YOU WANNA BUILD A SNOW MAN ?
    luogu P1579 哥德巴赫猜想(升级版)
    紫书 习题 10-25 UVa 1575 (有重复元素的全排列+暴搜)
  • 原文地址:https://www.cnblogs.com/AKMer/p/10243375.html
Copyright © 2011-2022 走看看