zoukankan      html  css  js  c++  java
  • 【CodeForces】CF Round 641 (Div.2)

    CF Round 641 (Div.2)/CF1350

    比赛时秒了 (A)(B),然后后面又肝出了 (C) 然后 (D) 不会做滚粗。最终 rating (+97) 上蓝。

    A. Orac and Factors

    显然是个结论题。推一下便可发现,对于一个 (n)

    (n) 是质数,那么它的变化必然是 (n o 2n o 2n+2 o 2n+4 o ... o 2n+2(k-1)),所以答案是 (2(n+k-1))

    (n) 是合数,那么它加上自己的最小质因子肯定是偶数,设 (s_i)(i) 的最小质因子,所以必然是 (n o n+s_n o n+s+2 o ... o n+s_n+2(k-1)),所以答案是 (n+s_n+2(k-1))

    #include<bits/stdc++.h>
    #define int long long
    using namespace std;
    const int N=1e6+9;
    int sm[N]; bool npr[N];
    void pr(){
    	npr[1]=1;
    	for(int i=2;i<=1000000;i++){
    		if(!npr[i]){
    			for(int j=i;j<=1000000/i;j++)
    				if(!npr[i*j]) sm[i*j]=i,npr[i*j]=1;
    		}
    	}
    }
    signed main(){
    	int T; cin>>T;
    	pr();
    	while(T--){
    		int n,k; scanf("%lld%lld",&n,&k);
    		if(!npr[n]){
    			printf("%lld
    ",2*(n+k-1));
    		}else{
    			printf("%lld
    ",n+sm[n]+2*(k-1));
    		}
    	}
    	return 0;
    }
    

    B. Orac and Models

    很思博的一个 (dp) 题。就是按照最长单调递增子序列的方法做,然后只有自己的约数可以转移到自己。(O(nsqrt{n}))

    #include<bits/stdc++.h>
    using namespace std;
    const int N=1e5+9;
    int a[N],f[N];
    int main(){
    	int T; cin>>T;
    	while(T--){
    		int n; scanf("%d",&n); int ans=1;
    		for(int i=1;i<=n;i++) scanf("%d",&a[i]),f[i]=1;
    		for(int i=2;i<=n;i++){
    			for(int j=1;j<=sqrt(i);j++){
    				if(i%j==0){
    					if(a[j]<a[i]) f[i]=max(f[i],f[j]+1);
    					if(a[i/j]<a[i]) f[i]=max(f[i],f[i/j]+1);
    				}
    			}
    			ans=max(ans,f[i]);
    		}
    		printf("%d
    ",ans);
    	}
    	return 0;
    }
    

    C. Orac and LCM

    我们可以推得,如果有一个质因子同时不在两个数中出现,设这两个数为 (a_i)(a_j),那么 (operatorname{lcm} (a_i,a_j)) 肯定不包含这个质因子,所以最终的答案中不会有这个质因子。

    所以一个质因子在答案中出现的必要条件是这个质因子必须在至少 (n-1) 个数中出现。

    我们考虑每个数的指数。如果这个数在由于最终的 (operatorname{gcd}) 中这个质因子的指数应该是所有 (lcm) 中的指数的最小值。如果这个数在 (n-1) 个数中出现过,那么肯定就是在原数列中这个质因子出现的指数的最小值。如果在 (n) 个数都包含这个质因子,那么就是次小值。统计一下出现次数,指数最小值和次小值即可。

    #include<bits/stdc++.h>
    #define int long long
    using namespace std;
    const int N=100009;
    int n,a[N],cnt[N*2],mn[N*2],cmn[N*2],ans=1; bool npr[2*N];
    void pr(){
    	npr[1]=1;
    	for(int i=2;i<=N*2-10;i++){
    		if(!npr[i]){
    			for(int j=i;j<=(N*2-10)/i;j++)
    				if(!npr[i*j]) npr[i*j]=1;
    		}
    	}
    }
    int qp(int a,int b){
        return (b==0?1:(b%2?qp(a*a,b/2)*a:qp(a*a,b/2)));
    }
    signed main(){
    	scanf("%lld",&n);
    	pr();
    	memset(mn,0x3f,sizeof(mn)),memset(cmn,0x3f,sizeof(cmn));
    	for(int i=1;i<=n;i++){
    		scanf("%lld",&a[i]);
    		for(int j=1;j<=sqrt(a[i]);j++){
    			if((a[i]%j==0)&&(!npr[j])){
    				cnt[j]++;
    				int tmp=a[i],tot=0;
    				while(tmp%j==0){
    					tot++,tmp/=j;
    				}
    				if(tot<=mn[j]) cmn[j]=mn[j],mn[j]=tot;
    				else if(tot<cmn[j]) cmn[j]=tot;
    			}
    			if((a[i]%j==0)&&(!npr[a[i]/j])&&(a[i]/j!=j)){
    				cnt[a[i]/j]++;
    				int tmp=a[i],tot=0;
    				while(tmp%(a[i]/j)==0){
    					tot++,tmp/=(a[i]/j);
    				}
    				if(tot<=mn[a[i]/j]) cmn[a[i]/j]=mn[a[i]/j],mn[a[i]/j]=tot;
    				else if(tot<cmn[a[i]/j]) cmn[a[i]/j]=tot;
    			}
    		}
    	}
    	for(int i=2;i<=N*2-10;i++){
    		if((!npr[i])&&cnt[i]==n) ans*=qp(i,cmn[i]);
    		else if(!npr[i]&&cnt[i]==n-1) ans*=qp(i,mn[i]);
    	}
    	printf("%lld",ans);
    	return 0;
    }
    

    D. Orac and Medians

    这道题有一个转换,就是其实只有 (3) 种数,大于 (k),小于 (k) 和等于 (k),我们分别转换为 (2)(0)(1)。我们要把所有区间化为 (1)

    如果这个序列没有 (1),那么答案肯定是no

    然后我们可以发现,(2) 的影响不大,因为一旦 (1)(2) 相邻,那么合并一下一定是 (1)。但是 (0) 的影响就很大。对于一个长度为 len 的区间,一旦中位数是 (0) 那么这个区间就是 (0),所以我们要判断是不是所有区间的中位数都是 (0)

    我们化简亿下这个条件。一旦一个区间是可以化成 (1) 的,那么一定存在一个长度为 (3) 的区间是可以化成 (1) 的;如果所有区间都不可以,那么所有长度为 (3) 的也都不可以。所以我们只需要判断长度为 (3) 的即可。存在这样的区间,就是存在一个长度为 (3) 的区间使得里面 (0) 的个数不大于 (1)

    #include<bits/stdc++.h>
    using namespace std;
    const int N=1e6+9;
    int a[N],s[N];
    int main(){
    	int T; cin>>T;
    	while(T--){
    		bool ans=0;
    		int n,k; scanf("%d%d",&n,&k);
    		for(int i=1;i<=n;i++){
    			scanf("%d",&a[i]);
    			if(a[i]>=k) s[i]=s[i-1]+1;
    			else s[i]=s[i-1];
    			if(a[i]==k) ans=1;
    		}
    		if(!ans){puts("no");continue;}
    		ans=0;
    		for(int i=1;i<=n-2;i++){
    			ans|=(s[i+2]-s[i-1]>1);
    		}
    		if(n==1) ans=(a[n]==k);
    		if(n==2) ans=((a[1]==k&&a[2]>=k)||(a[2]==k&&a[1]>=k));
    		if(ans) puts("yes");
    		else puts("no");
    	}
    	return 0;
    }
    

    E. Orac and Game of Life

    一个方格如果在当前回合变化了,那么下一个回合也会变化。所以假设知道了这个方格是在第 (f_{i,j}) 回合第一次变化,那么我们可以很快的求出他在第 (k) 个回合的状态。

    如果一个方格在第 (j) 回合变化,那么在第 (j+1) 回合,它周围所有还没有变化的方格都会开始变化。所以这相当于一个向外扩散的过程(想象一下共振),我们可以用 BFS 解决。

    #include<bits/stdc++.h>
    using namespace std;
    const int N=1e3+9;
    int n,m,t,a[N][N],f[N][N]; bool vst[N][N];
    bool ok(int x,int y){return x>0&&x<=n&&y>0&&y<=m;}
    int dx[4]={1,0,-1,0},dy[4]={0,1,0,-1};
    struct node{int x,y;};
    void bfs(){
    	queue<node>q;
    	for(int i=1;i<=n;i++)
    		for(int j=1;j<=m;j++){
    			bool move=0;
    			for(int k=0,nx,ny;k<4;k++)
    				move|=(ok(nx=i+dx[k],ny=j+dy[k])&&a[i][j]==a[nx][ny]);
    			if(move) q.push((node){i,j}),f[i][j]=1,vst[i][j]=1;
    		}
    	while(!q.empty()){
    		int x=q.front().x,y=q.front().y; q.pop();
    		for(int k=0,nx,ny;k<4;k++)
    			if(ok(nx=x+dx[k],ny=y+dy[k])&&!vst[nx][ny]){
    				f[nx][ny]=f[x][y]+1;
    				q.push((node){nx,ny});
    				vst[nx][ny]=1;
    			} 
    	}
    }
    int main(){
    	scanf("%d%d%d",&n,&m,&t);
    	for(int i=1;i<=n;i++){
    		string s; cin>>s;
    		for(int j=1;j<=m;j++) a[i][j]=s[j-1]-'0';
    	}
    	bfs();
    	for(int i=1,x,y;i<=t;i++){
    		long long p; scanf("%d%d%lld",&x,&y,&p);
    		if(f[x][y]==0) printf("%d
    ",a[x][y]);
    		else printf("%d
    ",a[x][y]^(max(p-f[x][y]+1,0ll)%2));
    	}
    	return 0;
    }
    
  • 相关阅读:
    深入分析 Python 的垃圾回收机制
    9.26
    Web安全之ML--构建机器学习工具箱
    第八节--图的数据结构及其算法
    第七节--树形结构及其算法
    第六节--堆栈与队列算法
    第四节--查找与哈希算法
    第三节--排序算法
    第二节--常用数据结构
    第一节--走入算法的世界
  • 原文地址:https://www.cnblogs.com/TetrisCandy/p/12880813.html
Copyright © 2011-2022 走看看