Codeforces Round #748 (Div. 3)A,B,C,D1,E题解

A. Elections
传送门

题意:

给你a,b,c三个数,问你让这三个数每一个都严格大于其它俩数的最小花费。

思路:

分别对a,b,c进行判断即可。

#include<bits/stdc++.h>
#define ll long long
using namespace std;
#define eps 0.00000001

int main()
{
    
    
	int t;
	cin>>t;
	while(t--)
	{
    
    
		ll a,b,c;
		cin>>a>>b>>c;
		if(a > b && a > c)cout<<0<<" ";
		else
		cout<<max(b-a, c-a)+1<<" ";
		
		if(b > a && b > c)cout<<0<<" ";
		else cout<<max(a-b,c-b)+1<<" ";
		
		if(c > a && c > b)cout<<0<<" ";
		else cout<<max(a-c,b-c)+1<<" ";
		cout<<endl; 
		
		
	}
}
 

B. Make it Divisible by 25

传送门

题意:

给你一个数,问你删除这个数中多少个数字最后得到的结果能整除25.

思路:

一个数的个位和十位组成的数如果能整除25,那么这个数一定能整除25,同时,因为这道题输入的数不包含前导0,所以个位和十位都是0也满足条件。
只需要找到最靠右的两个满足条件的数即可得出答案。

#include<bits/stdc++.h>
#define ll long long
using namespace std;
#define eps 0.00000001
char a[1000];

int main()
{
    
    
	int t;
	cin>>t;
	while(t--)
	{
    
    
		scanf("%s",a+1);
		int flag = 0;
		int ans = 0x3f3f3f3f;
		int n = strlen(a+1);
		for(int i = n; i >= 1; i--)
		{
    
    
			if(a[i] == '5')flag = 1;
			else if(a[i] == '2' || a[i] == '7')
			{
    
    
				if(flag)ans = min(ans, (n-i+1)-2);
			}
		}
		flag = 0;
		for(int i = n; i >= 1; i--)
		{
    
    
			if(flag)
			{
    
    
				if(a[i] == '0' || a[i] == '5')
				{
    
    
					ans = min(ans, (n-i+1)-2);
				}
			}
			if(a[i] == '0')
			{
    
    
				flag = 1;
			}
		}
		cout<<ans<<endl;
	}
}
 

Save More Mice

传送门

题意:

给你k个老鼠的位置和老鼠洞的位置n,开始时,猫在第0处,每次选择一只老鼠向老鼠洞移动1个单位,而后猫向老鼠洞移动一个单位(这个动作发生在老鼠移动之后),当猫碰到老鼠,就会吃掉它,问你最多有多少只老鼠能到大老鼠洞。

思路:

二分答案。
先将老鼠位置排序,二分枚举老鼠存活的个数mid,将mid带入check函数去判断其是否满足条件。

#include<bits/stdc++.h>
#define ll long long
using namespace std;
#define eps 0.00000001
ll a[400010];
ll n,k;
int check(ll mid)
{
    
    
	ll sum = 0;
	for(int i = k; i >= k-mid; i--)
	{
    
    
		sum += (n-a[i]);
	}
	if(sum > n)return 0;
	else if(sum < n)return 1;
	else return 2;
}
int main()
{
    
    
	int t;
	cin>>t;
	while(t--)
	{
    
    
		cin>>n>>k;
		for(int i = 1; i <= k; i++)
		{
    
    
			cin>>a[i];
		}
		sort(a+1,a+1+k);
		ll l = 0, r = k;
		while(l < r)
		{
    
    
			ll mid = (l+r)/2;
			if(check(mid) == 1)
			{
    
    
				l = mid+1;
			}
			else if(check(mid) == 0)
			{
    
    
				r = mid;
			}
			else
			{
    
    
				break;
			}
		}
		cout<<(l+r)/2<<endl;
	}
}
 

D1. All are Same

传送门

题意:

给你一串数字序列,你可以对整串序列中的任何一个数字进行任意次的减k操作,问你在保证能使整个序列中的数最终变得相同的前提下能得到的最大的k是多少,如果k无限大,输出-1。

思路:

显而易见的:只有当序列中的元素初始全都相等时,k才能取无限大。(反证法:当k为无穷大并且序列中数字不全相等,因为序列中的数字不可能为无穷大,所以如果你至少进行了一次减k操作,都会使得序列中的某一个元素变得无穷大,从而序列中元素无法相等)
对于一般的序列:
我们对这个序列进行一次排序,设这个序列为a,显然,k无法超过 m i n ( a i − a i − 1 ) min(a_i-a_{i-1}) min(aiai1),而这个约束条件显然还不够,在求得每一个 d i = a i − a i − 1 d_i=a_i-a_{i-1} di=aiai1时,会发现, k必须要为所有 d i d_i di的最大公约数,这样在进行减k操作时才能保证最终获得的a序列中的数相同。

E. Gardener and Tree

传送门

题意:

给你一棵有n个节点的树和k次操作,每次操作都会删除所有的叶子节点,问你k次操作后剩余多少节点。

思路:

拓补排序。
用邻接表存储图,同时存储每个点所连接的边数,每次删除边数为1的点和这条边…拓补板子。

#include<bits/stdc++.h>
#define ll long long
using namespace std;
int in_dex[400010];
vector<int>g[400010];
queue<int>q;
int vis[400010];

int main()
{
    
    
	int t;
	cin>>t;
	while(t--)
	{
    
    
		int n,k;
		cin>>n>>k;
		for(int i = 1; i <= n-1; i++)
		{
    
    
			int u,v;
			scanf("%d%d",&u,&v);
			in_dex[u]++;
			in_dex[v]++;
			g[u].push_back(v);
			g[v].push_back(u);
		}
		if(n == 1)
		{
    
    
			if(k >= 1)cout<<0<<endl;
			else cout<<1<<endl;
			continue;;
		}
		int cnt = 0;
		int sum = 0;
		for(int i = 1; i <= n; i++)
		{
    
    
			if(in_dex[i] == 1)q.push(i),vis[i] = 1;
		}
		
		while(!q.empty())
		{
    
    
			int now = q.front();
			q.pop();
			sum++;
			if(vis[now] == k)continue;
			for(int i = 0; i < g[now].size(); i++)
			{
    
    
				in_dex[g[now][i]]--;
				if(!vis[g[now][i]] && in_dex[g[now][i]] == 1)
				{
    
    
					q.push(g[now][i]);
					vis[g[now][i]] = vis[now]+1;
				}
			}
		}
		cout<<n-sum<<endl;
		for(int i = 1; i <= n; i++)g[i].clear(),in_dex[i] = 0,vis[i] = 0;
	}
}


Guess you like

Origin blog.csdn.net/p15008340649/article/details/120755392