2017中国大学生程序设计竞赛-哈尔滨站 极少部分题解

2017中国大学生程序设计竞赛-哈尔滨站

F题 Permutation

跟榜签到题

想排列的英文想了半天,结果发现题目不就是吗...

直接STL暴力打表找规律

发现答案形如 1 n 2 n-1 3 n-2 4...

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

H题 A Simple Stone Game

本来是没准备贴这道题的,但是比赛的时候莫名打错然后自闭了

(一个mod使{sum_{i=1}^{i=n}b_i}\%mod=0 iff sum\%mod=0)

显然质因数肯定比因数的解更优,所以只用求出所有质因数然后枚举就行了

注意一下 ans初始化为sum-(max(a_i)) 因为如果素数筛不够大的话sum刚好是素数就刚好枚举不到sum这个素数(爆内存)

但是似乎数据没有这个坑?

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+5,M=3e5+5;
int T,n,a[N],maxn,ss[N],k,b[N];
long long ans,sum;
bool use[M];
vector <int> f;
void pd()
{
	use[1]=1;
	for(int i=2;i<M-3;i++)
	{
		if(use[i]==0)
			ss[++k]=i;
		for(int j=1;j<=k&&ss[j]*i<M-3;j++)
		{
			use[ss[j]*i]=1;
			if(i%ss[j]==0)
				break;
		}
	}
}
int main()
{
	
	scanf("%d",&T);
	pd();
	while(T--)
	{
		scanf("%d",&n);
		sum=0;
		maxn=-1;
		for(int i=1;i<=n;i++)
		{
			scanf("%d",&a[i]);
			sum+=a[i];
			maxn=max(a[i],maxn); 
		}
		ans=sum-maxn;
		f.clear();
		for(int i=1;i<=k&&ss[i]<=sum;i++)
		{
			if(sum%ss[i]==0)
			{
				f.push_back(ss[i]);
				while(sum%ss[i]==0) 
					sum/=ss[i];
			}
		}
		for(auto mod:f)
		{
			for(int i=1;i<=n;i++)
				b[i]=a[i]%mod;
			sort(b+1,b+n+1);
			int posl=1,posr=n;
			long long tempans=0;
			while(posl<posr)
			{
				if(b[posl]+b[posr]>mod)
				{
					tempans=tempans+mod-b[posr];
					b[posl]=b[posl]-mod+b[posr];
					posr--;
				}
				else
				{
					tempans+=b[posl];
					b[posr]+=b[posl];
					posl++;
				}	
			}
			ans=min(ans,tempans);
		}
		printf("%lld
",ans);
	}
	return 0;
} 
/*
2
5
1 2 3 4 5
1
2 
5
23404 19878 8440 10483 19291
*/

D 题 X-men

题意:

给你一些点,只要存在两点之间距离大于1,就可以移动,每移动一步算1s,两个点总是尽可能的最短时间内相遇|相邻,求最长的时间

虽然两个点距离可能是奇数,但是相邻的时候也相当于相遇所以路程除二,所以不影响"相遇"时间

求最长时间也就是求两点之间的最长距离/2期望都是唬人的

开始想LCA,emmm想多了

还是之间枚举所有点直接BFS算了

#include<bits/stdc++.h>
using namespace std;
const int N=1e4+5;
int T,n,m,x,y,tot,a[N],ans;
bool use[N],vis[N];
struct node
{
	int pos,step;
};
vector <int> f[N];
queue <node> q;
int bfs(int x,int cnt)
{
	while(!q.empty())
		q.pop();
	memset(vis,0,sizeof(vis));
	vis[x]=1;
	q.push((node){x,0});
	while(!q.empty())
	{
		node temp=q.front();
		q.pop();
		if(use[temp.pos]==1)
			cnt--;
		if(cnt==0)
			return temp.step;
		for(auto i:f[temp.pos])
		{
			if(vis[i]==0)
			{
				vis[i]=1;
				q.push((node){i,temp.step+1});
			}
		}
	}
}
int main()
{
	scanf("%d",&T);
	while(T--)
	{
		
		scanf("%d %d",&n,&m);
		for(int i=1;i<=n;i++)
			f[i].clear();
		memset(use,0,sizeof(use));
		tot=0;
		for(int i=1;i<=m;i++)
		{
			scanf("%d",&x);
			if(use[x]==0)
			{
				a[++tot]=x; 
				use[x]=1;
			}
		} 
		for(int i=1;i<n;i++)
		{
			scanf("%d %d",&x,&y);
			if(x==y)
				continue;
			f[x].push_back(y);
			f[y].push_back(x);
		}
		ans=0;
		for(int i=1;i<=tot;i++)
		{
			ans=max(ans,bfs(a[i],tot));
		}
		printf("%d.00
",ans/2);
	}
	return 0;
}
原文地址:https://www.cnblogs.com/cherrypill/p/13157993.html