Codeforces Round #748 (Div. 3)A到E

A. Elections

题意

3个人各有一个票数,问每个人票数严格大于其他人还需要多少票

思路

三个数排序一下,如果这个人的票数是最多的没有人和他相同就输出0,有人和他一
样大就输出1,如果票数不是最多的就输出最大减去他的票数加一。

ac代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long
typedef pair<int,int> PII;
const int maxn=1e6+10;
const double eps=1e-5;
int n;
int a[maxn];
int b[maxn];
int main(){
	int t; scanf("%d",&t);
	while(t--){
		scanf("%d%d%d",&a[0],&a[1],&a[2]);
		b[0] = a[0],b[1] = a[1], b[2] = a[2];
		sort(a, a + 3);
		if(b[0] != a[2]){
			printf("%d ",a[2] - b[0] + 1);
		}else if(a[1] == a[2]){
			printf("1 ");
		}else{
			printf("%d ",0);
		}
		if(b[1] != a[2]){
			printf("%d ",a[2] - b[1] + 1);
		}else if(a[1] == a[2]){
			printf("1 ");
		}else{
			printf("%d ",0);
		}
		if(b[2] != a[2]){
			printf("%d ",a[2] - b[2] + 1);
		}else if(a[1] == a[2]){
			printf("1 ");
		}else{
			printf("%d",0);
		}
		printf("\n");
	}
	return 0;
}

B. Make it Divisible by 25

题意

给你一个数要你删除一些数字后能被25整除,问最少删除多少个数字。

思路

能被25整除的数后缀一定是25507500。所以找第一次出现这些后缀需要删除
的最小次数。

ac代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long
typedef pair<int,int> PII;
const int maxn=1e6+10;
const double eps=1e-5;
int main(){
	int t; scanf("%d",&t);
	while(t--){
		string s;
		cin >> s;
		int k = s.size() - 1;
		int flag = 0;
		int ans = 0x3f3f3f3f;
		for(int i = k; i >= 0; i --){
			if(s[i] == '5'){
				flag = 1;
			}
			if(s[i] == '2' && flag == 1){
				ans = min(ans,k - i - 1);
				break;
			}
		}
		flag = 0;
		for(int i = k; i >= 0; i --){
			if(s[i] == '0'){
				flag = 1;
			}
			if(s[i] == '5' && flag == 1){
				ans = min(ans,k - i - 1);
				break;
			}
		}
		flag = 0;
		for(int i = k; i >= 0; i --){
			if(s[i] == '5'){
				flag = 1;
			}
			if(s[i] == '7' && flag == 1){
				ans = min(ans,k - i - 1);
				break;
			}
		}
		flag = 0;
		for(int i = k; i >= 0; i --){
			if(s[i] == '0' && flag == 1){
				ans = min(ans,k - i - 1);
				break;
			}
			if(s[i] == '0'){
				flag = 1;
			}
		}
		printf("%d\n",ans);
	}
	return 0;
}

C. Save More Mice

题意

一只猫在0的位置,有多老鼠分布在一道n - 1的为值,每次一只老鼠移动一次然后
猫移动,问最多又多少只老鼠可以跑到n点。

思路

每次移动最后一只老鼠

ac代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long
typedef pair<int,int> PII;
const int maxn=1e6+10;
const double eps=1e-5;
int a[maxn];
int main(){
	int t; scanf("%d",&t);
	while(t--){
		int n,k; scanf("%d%d",&n,&k);
		for(int i = 1; i <= k;i ++){
			scanf("%d",&a[i]);
		}
		sort(a + 1, a + 1 + k);
		int ans = 0;
		int now = 0;
		for(int i = k; i >= 1; i --){
			if(a[i] > now){
				ans++;
				now = now + n - a[i];
			}else{
				break;
			}
		}
		printf("%d\n",ans);
	}
	return 0;
}

D1. All are Same

题意

给一串数a[i],没吃可以选一个a[i]减去k,问最大的k是多少,无限大输出-1

思路

如果变为相同最后肯定是变为最小的,找所有数变为最小的所需要的k的gcd

ac代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long
typedef pair<int,int> PII;
const int maxn=1e6+10;
const double eps=1e-5;
int a[maxn];
int main(){
	int t; scanf("%d",&t);
	while(t--){
		int n; scanf("%d",&n);
		int flag = 0;
		for(int i = 1; i <= n; i ++){
			scanf("%d",&a[i]);
		}
		for(int i = 1; i <= n;i ++){
			if(a[i] != a[1]) flag = 1;
		}
		if(flag == 0){
			printf("-1\n");
			continue;
		}
		sort(a + 1, a + 1 + n);
		int ans = -1;
		for(int i = 2; i <= n; i ++){
			if(a[i] == a[i - 1]) continue;
			int k = a[i] - a[i - 1];
			if(ans == -1){
				ans = k;
			}else{
				ans = __gcd(k, ans);
			}
		}
		printf("%d\n",ans);
	}
	return 0;
}

D2. Half of Same

题意

和D1一样不过要求至少有一半的ai变为一样

思路

枚举最小会变到多少,然后算出其他数到这个数的差,k值一定就是这个差的因数对
k因数分解就可以得到所有可能k得取值,然后重大到小枚举k的取值,看有多少个差
的因数含k,大于n / 2 - 1的话就是一个可能答案,最后取最大值,还有一些细节
看代码。

ac代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long
typedef pair<int,int> PII;
const int maxn=1e6+10;
const double eps=1e-5;
unordered_map<int,int> e;
int a[maxn];
priority_queue<int> qq;
int main(){
	int t; scanf("%d",&t);
	while(t--){
		int n; scanf("%d",&n);
		for(int i = 1; i <= n; i ++){
			scanf("%d",&a[i]);
		}
		sort(a + 1,a + 1 + n);
		int cnt = 1;
		for(int i = 2; i <= n; i ++){
			if(cnt >= n / 2) break;
			if(a[i] == a[i - 1]){
				cnt ++;
			}else{
				cnt = 1;
			}
		}
		if(cnt >= n / 2){
			printf("-1\n");
		}else{
			int ans = 0;
			for(int i = 1; i <= n / 2 + 1; i ++){
				int cnt = 1;
				for(int j = i + 1; j <= n; j ++){
					if(a[j] == a[i]) cnt ++;
				}
				for(int j = i + 1; j <= n; j ++){
					int p = a[j] - a[i];
					if(p == 0){
						continue;
					}else{
						for(int i = 1; i <= p / i; i ++){
							if(p % i == 0){
								if(e[i] == 0){
									qq.push(i);
								}
								if(e[p / i] == 0){
									qq.push(p / i);
								}
								e[i] ++;
								if(i == p / i) continue;
								e[p / i] ++;
							}
						}
					}
				}
				while(!qq.empty()){
					int t = qq.top();
					qq.pop();
					if(e[t] >= n / 2 - cnt) {
						ans = max(ans, t);
						break;
					}
				}
				while(!qq.empty()){
					qq.pop();
				}
				e.clear();
			}
			printf("%d\n",ans);
		}
	}
	return 0;
}

E. Gardener and Tree

题意

问一棵树删去k次叶子节点后还剩多少个点,每次删除是散去所有的叶子节点。

思路

记录下每个点的连接,和入度,如果入度为一就进入队列,删除时把队列里的节点
拿出来,跟新与他相连的节点入度减一。

ac代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long
typedef pair<int,int> PII;
const int maxn=1e6+10;
const double eps=1e-5;
vector<int> g[maxn];
int ru[maxn];
int vis[maxn];
queue<int> now;
int main(){
	int t; scanf("%d",&t);
	while(t--){
		int n,k; scanf("%d %d",&n,&k);
		for(int i = 1; i <= n; i ++){
			g[i].clear();
			ru[i] = 0;
		}
		while(!now.empty()){
			now.pop();
		}
		for(int i = 1; i < n;i ++){
			int x,y; scanf("%d %d",&x,&y);
			g[x].push_back(y);
			g[y].push_back(x);
			ru[x] ++;
			ru[y] ++;
		}
		for(int i = 1; i <= n; i ++){
			if(ru[i] == 1) now.push(i);
		}
		if(n == 1) now.push(1);
		int ans = n;
		while(k > 0){
			if(now.empty()) break;
			int o = now.size();
			ans = ans - o;
			for(int i = 0; i < o; i ++){
				int q = now.front();
				now.pop();
				for(int j = 0; j < g[q].size(); j ++){
					ru[g[q][j]] --;
					if(ru[g[q][j]] == 1){
						now.push(g[q][j]);
					}
				}
			}
			k --;
		}
		printf("%d\n",ans);
	}
	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

顺序并不响影阅读

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值