zoukankan      html  css  js  c++  java
  • 2015 编程之美初赛第一场 AC题

    题目1 : 彩色的树

    时间限制:2000ms
    单点时限:1000ms
    内存限制:256MB

    描述

    给定一棵n个节点的树,节点编号为1, 2, …, n。树中有n - 1条边,任意两个节点间恰好有一条路径。这是一棵彩色的树,每个节点恰好可以染一种颜色。初始时,所有节点的颜色都为0。现在需要实现两种操作:

    1. 改变节点x的颜色为y;

    2. 询问整棵树被划分成了多少棵颜色相同的子树。即每棵子树内的节点颜色都相同,而相邻子树的颜色不同。

    输入

    第一行一个整数T,表示数据组数,以下是T组数据。

    每组数据第一行是n,表示树的节点个数。接下来n - 1行每行两个数i和j,表示节点i和j间有一条边。接下来是一个数q,表示操作数。之后q行,每行表示以下两种操作之一:

    1. 若为"1",则询问划分的子树个数。

    2. 若为"2 x y",则将节点x的颜色改为y。

    输出

    每组数据的第一行为"Case #X:",X为测试数据编号,从1开始。

    接下来的每一行,对于每一个询问,输出一个整数,为划分成的子树个数。

    数据范围

    1 ≤ T ≤ 20

    0 ≤ y ≤ 100000

    小数据

    1 ≤ n, q ≤ 5000

    大数据

    1 ≤ n, q ≤ 100000

    样例输入
    2
    3
    1 2
    2 3
    3
    1
    2 2 1
    1
    5
    1 2
    2 3
    2 4
    2 5
    4
    1
    2 2 1
    2 3 2
    1
    
    样例输出
    Case #1:
    1
    3
    Case #2:
    1
    5

    其实只需要考虑修改点对相邻的点影响就好。例如原来相同改成不同就+1如此。用枚举,T了大数据。正确做法应该是预先存下相邻点的情况,再处理。
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    using namespace std;
    
    const int MAXN=100050;
    
    int color[MAXN];
    struct edge{
    	int u,v;
    	int next;
    }edge[MAXN*2];
    int head[MAXN];
    int tot;
    
    void addedge(int u,int v){
    	edge[tot].u=u;
    	edge[tot].v=v;
    	edge[tot].next=head[u];
    	head[u]=tot++;
    }
    
    int main(){
    	int T,icase=0,u,v,op,x,y;
    	scanf("%d",&T);
    	while(T--){
    		int n,q;
    		scanf("%d",&n);
    		tot=0;
    		memset(color,0,sizeof(int)*(n+10));
    		memset(head,-1,sizeof(int)*(n+10));
    		for(int i=1;i<n;i++){
    			scanf("%d%d",&u,&v);
    			addedge(u,v);
    			addedge(v,u);
    		}
    		scanf("%d",&q);
    		int ans=1;
    		printf("Case #%d:
    ",++icase);
    		for(int i=1;i<=q;i++){
    			scanf("%d",&op);
    			if(op==1)
    			printf("%d
    ",ans);
    			else{
    				scanf("%d%d",&x,&y);
    				int pre=color[x];
    				for(int e=head[x];e!=-1;e=edge[e].next){
    					int v=edge[e].v;
    					if(color[v]==pre){
    						if(color[v]!=y)
    						ans++;
    					}
    					else if(color[v]!=pre){
    						if(color[v]==y)
    						ans--;
    					}
    				}
    				color[x]=y;
    			}
    		}
    	}
    	return 0;
    }
    

      

    题目3 : 质数相关

    时间限制:2000ms
    单点时限:1000ms
    内存限制:256MB

    描述

    两个数a和 b (a<b)被称为质数相关,是指a × p = b,这里p是一个质数。一个集合S被称为质数相关,是指S中存在两个质数相关的数,否则称S为质数无关。如{2, 8, 17}质数无关,但{2, 8, 16}, {3, 6}质数相关。现在给定一个集合S,问S的所有质数无关子集中,最大的子集的大小。

    输入

    第一行为一个数T,为数据组数。之后每组数据包含两行。

    第一行为N,为集合S的大小。第二行为N个整数,表示集合内的数。

    输出

    对于每组数据输出一行,形如"Case #X: Y"。X为数据编号,从1开始,Y为最大的子集的大小。

    数据范围

    1 ≤ T ≤ 20

    集合S内的数两两不同且范围在1到500000之间。

    小数据

    1 ≤ N ≤ 15

    大数据

    1 ≤ N ≤ 1000

    样例输入
    3
    5
    2 4 8 16 32
    5
    2 3 4 6 9
    3
    1 2 3
    
    样例输出
    Case #1: 3
    Case #2: 3
    Case #3: 2

    可证此图必定无环。是一棵树,树形DP即可。同时树也是二分图,二分图最大独立集也可做。
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define LL long long
    using namespace std;
    
    const int MAXN=500050;
    
    bool isprime[MAXN];
    
    int prime[MAXN];
    
    void predo(){
    	memset(isprime,false,sizeof(isprime));
    	int tot=0;
    	for(int i=2;i<=MAXN;i++){
    		if(!isprime[i]) prime[tot++]=i;
    		for(int j=0;j<tot;j++){
    			if((LL)i*(LL)prime[j]>(LL)MAXN) break;
    			isprime[i*prime[j]]=true;
    			if(i%prime[j]==0) break;
    		}
    	}
    }
    
    int num[1010];
    bool vis[1010];
    
    struct edge{
    	int u,v;
    	int next;
    }edge[3000];
    int dp[1050][2];
    int tot,head[1050];
    
    void addedge(int u,int v){
    	edge[tot].u=u;
    	edge[tot].v=v;
    	edge[tot].next=head[u];
    	head[u]=tot++;
    }
    
    void dfs(int i){
    	vis[i]=true;
    	dp[i][1]=1; dp[i][0]=0;
    	for(int e=head[i];e!=-1;e=edge[e].next){
    		int v=edge[e].v;
    		if(!vis[v]){
    			dfs(v);
    			dp[i][1]+=dp[v][0];
    			dp[i][0]+=max(dp[v][1],dp[v][0]);
    		}
    	}
    }
    
    int main(){
    	predo();
    	int T,icase=0;
    	scanf("%d",&T);
    	while(T--){
    		int n;
    		scanf("%d",&n);
    		tot=0;
    		memset(vis,false,sizeof(vis));
    		memset(head,-1,sizeof(head));
    		for(int i=1;i<=n;i++)
    		scanf("%d",&num[i]);
    		sort(num+1,num+n+1);
    		for(int i=1;i<=n;i++){
    			for(int j=i+1;j<=n;j++){
    				if(num[j]%num[i]==0){
    					if(!isprime[num[j]/num[i]]){
    						addedge(i,j);
    						addedge(j,i);
    					}
    				}
    			}
    		}
    		int ans=0;
    		for(int i=1;i<=n;i++){
    			if(!vis[i]){
    				dfs(i);
    				ans+=max(dp[i][0],dp[i][1]);
    			}
    		}
    		printf("Case #%d: %d
    ",++icase,ans);
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    Java实现 蓝桥杯VIP 算法训练 王后传说
    Java实现 蓝桥杯VIP 算法训练 王后传说
    Java实现 蓝桥杯VIP 算法训练 特殊的数字四十
    win7桌面图标小盾牌怎么去掉(2种方法)
    使用GO语言灵活批量ssh登录服务器执行操作
    2016 Web 开发资源工具大搜罗
    sqlite的源代码加密,以及其它一些文章
    SQLite 对中文路径的支持(用到了StringToWideChar和Utf8Encode在D7的System单元中自带)
    AMD规范与CMD规范的区别
    值类型和引用类型、可空类型、堆和栈、装箱和拆箱
  • 原文地址:https://www.cnblogs.com/jie-dcai/p/4514181.html
Copyright © 2011-2022 走看看