ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

2022牛客暑假第五场加塞

2022-08-25 09:01:11  阅读:174  来源: 互联网

标签:sz ten int 第五场 lca dfs 牛客 res 加塞


M-Maimai DX 2077_"蔚来杯"2022牛客暑期多校训练营(加赛) (nowcoder.com)

阅读理解和膜你题。

double pts[5][5]={
	{1,1,0.8,0.5,0},
	{2,2,1.6,1.0,0},
	{3,3,2.4,1.5,0},
	{5,5,2.5,2,0},
	{1,0.5,0.4,0.3,0}
};
int num[4][5];
int sum[4];
double A,B,A0,B0;

int main(){
	for(int i=0;i<4;i++){
		for(int j=0;j<5;j++){
			scanf("%d",&num[i][j]);
			sum[i]+=num[i][j];
		}
	}

	for(int i=0;i<4;i++)A+=sum[i]*pts[i][0];
	B=sum[3]*pts[4][0];
	
	for(int i=0;i<4;i++){
		for(int j=0;j<5;j++){
			A0+=num[i][j]*pts[i][j];
		}
	}
	for(int j=0;j<5;j++){
		B0+=num[3][j]*pts[4][j];
	}
	
	printf("%lf",A0/A*100.0+B0/B);
	return 0;
}

H-Here is an Easy Problem of Zero-chan_"蔚来杯"2022牛客暑期多校训练营(加赛) (nowcoder.com)

dfs回溯,lca的一些小性质,质因子。

怪,并没有第一时间想到树形dp,而是想到了搜索回溯。

如何计算后缀零?

一个数如果乘以10,它就会出现一个后缀0,而10的质因子只有2和5。因此我们不必真的把所有lca乘起来,只需要计算它们乘起来之后质因子2和5的次数,两者取最小值即可。

如何处理lca?

  1. 首先,分析一个点和其他所有点之间lca的关系。很容易可以发现,一个点的lca只会在dfs当前的搜索路径上。如下图,3的lca只能是3、1、0这三个点。

  2. 其次,分析每个lca会出现的次数。因为如果知道它们出现的次数,很容易就可以算出它们的乘积中质因子2和5的次数。同样以点3为例,lca=3的情况恰好对应结点3的子树规模,lca=1的情况恰好等于结点1的子树规模减去结点3的子树规模,lca=0的情况恰好等于结点0的子树规模减去结点1(即结点3所在的分支)的子树规模。

  3. 最后,考虑如何更快地求出每个点的情况。因为dfs的过程中可以借助回溯很方便处理当前dfs的路径,所以一遍dfs就能把每个点的情况都求出来。

细节见代码:

#define x first
#define y second

const int N=1e5+5,M=2*N;
typedef long long ll;
typedef pair<ll,ll>PII;
int n,q;
PII ten[N];
int e[M],ne[M];
int h[N],idx;
int sz[N];
PII ans[N],res;

void adde(int x,int y){
	e[idx]=y; ne[idx]=h[x]; h[x]=idx++;
}

void dfs_sz(int u,int fa){
	sz[u]=1;
	for(int i=h[u];~i;i=ne[i]){
		int v=e[i];
		if(v==fa)continue;
		dfs_sz(v,u);
		sz[u]+=sz[v];
	}
}

void dfs_ten(int u,int fa){
    //先加上一整棵子树的质因子次数
	res={ res.x+ten[u].x*sz[u] , res.y+ten[u].y*sz[u] };
	for(int i=h[u];~i;i=ne[i]){
		int v=e[i];
		if(v==fa)continue;
        //往下搜索或者求答案,都需要先减去该分支的大小的以u为根的质因子次数
		res={res.x-ten[u].x*sz[v] , res.y-ten[u].y*sz[v]};
		ans[v]={res.x+ten[v].x*sz[v], res.y+ten[v].y*sz[v]};
		dfs_ten(v,u);
        //回溯
		res={res.x+ten[u].x*sz[v] , res.y+ten[u].y*sz[v]};
	}
    //回溯
	res={ res.x-ten[u].x*sz[u] , res.y-ten[u].y*sz[u] };
}

int main(){
	scanf("%d%d",&n,&q);
	int x,y;
	memset(h,-1,sizeof(h));
	for(int i=1;i<n;i++){
		scanf("%d%d",&x,&y);
		adde(x,y), adde(y,x);
	}
	
	for(int i=2;i<=n;i++){//求出每个数中质因子2和5的个数
		x=i;
		for(int j=2;x>1 && j<=5;j++){
			int cnt=0;
			while(x%j==0){
				cnt++;
				x/=j;
			}
			if(j==2)ten[i].x=cnt;
			if(j==5)ten[i].y=cnt;
		}
	}
	
	dfs_sz(1,0);
	ans[1]=res={0,0};//ans记录每个点的答案,res是dfs过程中的临时结果
	dfs_ten(1,0);
	
	for(int i=1;i<=q;i++){
		scanf("%d",&x);
		printf("%lld\n",min(ans[x].x,ans[x].y));
	}
	
	return (0-0);
}

E-Everyone is bot_"蔚来杯"2022牛客暑期多校训练营(加赛) (nowcoder.com)

很怪的博弈论题。

此题的关键在于:每个人都想最大化自己的冰红茶数量。

如果已经有n-p个人复读了,那么接下来那个人一定不会选择复读,因为如果他复读了,剩下的所有人也会一起复读,最后被惩罚的就是他了。、

对于n-2p,n-3p,n-4p....也是同理。最后可以得出,到(n mod p) + 1这个人的时候,复读就停止了。

n mod p个人一定一上来就会复读,因为如果他们不复读,后面的人就会抢占他们的机会。

const int N=1e3+5;
int n,p;
int a[N][N];

int main(){
	scanf("%d%d",&n,&p);
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			scanf("%d",&a[i][j]);
		}
	}
	
	for(int i=1;i<=n;i++){
		if(i<=n%p)printf("%d ",a[i][i]);
		else printf("%d ",0);
	}
	printf("\n");
	return 0;
}

标签:sz,ten,int,第五场,lca,dfs,牛客,res,加塞
来源: https://www.cnblogs.com/tshaaa/p/16623042.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有