• Codeforces Round #717 (Div. 2)D. Cut


    传送门

    题意:给一个长为n的数组,q次询问,区间l到r间需要最少分成多少段,使每一段的gcd等于1。

    题解:易知拥有同一质因子的数不能在一段中,考虑将每一个数质因数分解,再利用序列自动机可以求出每一个数前缀的最近的一个不合法的位置,很明显每个数只会连向它之前的一个位置,数组便形成了一颗树。再来看问题,求区间l至r需要分多少段,其实就是求r与l间的高度差,用倍增法求即可。

    #include<iostream>
    #include<vector>
    #include<cmath>
    using namespace std;
    const int N=1e5+7;
    int n,q,a[N];
    int prime[N],num[N];
    vector<int>ho[N];
    int ans[N],f[N][30];
    void solve() {
    	for(int i=2;i<sqrt(N);i++) {
    		if(!prime[i])prime[++prime[0]]=i;
    		for(int j=1;j<=prime[0]&&prime[j]<sqrt(N)/i;j++){
    			prime[prime[j]*i]=1;
    			if(i%prime[j]==0)break;
    		}
    	}
    }
    void add(int p,int z){
    	for(int i=1;i<=prime[0];i++){
    		if(z%prime[i]==0){
    			while(z%prime[i]==0){
    				z/=prime[i];
    			}
    			ho[p].push_back(prime[i]);
    		}
    	}
    	if(z!=1){
    		ho[p].push_back(z);
    	}
    }
    int main(){
    	solve();
    	scanf("%d%d",&n,&q);
    	for(int i=1;i<=n;i++){
    		scanf("%d",&a[i]);
    		add(i,a[i]);
    	}
    	for(int i=1;i<=n;i++){
    		f[i][0]=f[i-1][0];
    		for(int j=0;j<ho[i].size();j++){
    			int p=ho[i][j];
    			f[i][0]=max(f[i][0],num[p]);
    			num[p]=i;
    		}
    	}
    	for(int i=1;i<=20;i++){
    	    for(int j=1;j<=n;j++){
    		    f[j][i]=f[f[j][i-1]][i-1];
    	    }
    	}
    	for(int i=1;i<=q;i++){
    		int l,r;
    		scanf("%d%d",&l,&r);
    		int x=0;
    		for(int j=20;j>=0;j--){
    			if(f[r][j]>=l){
    				x+=1<<j;
    				r=f[r][j];
    			}
    		}
    		cout<<x+1<<"
    ";
    	}
    }
    
  • 相关阅读:
    数据结构八树和森林
    数据结构 七 二叉树的遍历
    python 的 encode 、decode、字节串、字符串
    TCP/IP
    pg 数据库操作
    nginx + lua 的 跳转命令
    lua string 下的函数
    lua 的匹配规则
    nginx的 ngx.var ngx.ctx ngx.req
    docker 网络模式 和 端口映射
  • 原文地址:https://www.cnblogs.com/whitelily/p/14689566.html
Copyright © 2020-2023  润新知