Codeforces Round #697 (Div. 3)

Codeforces Round #697 (Div. 3)

http://codeforces.com/contest/1475

A. Odd Divisor

题目大意

判断一个数是否存在一个大于1的奇因子

解决思路

不断的除2,然后最后检查即可

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

int main(){
	int t;cin >> t;
	while(t--){
		ll x;
		scanf("%lld",&x);
		while(x % 2 == 0) x /= 2;
		if(x > 1){
			puts("YES");
		}else{
			puts("NO");
		}
	}
	return 0;
}

B. New Year’s Number

讲真,这道题我本打算不写题解的,但我tm竟然能wa??原地退役吧,腾位置

题目大意

判断n能否有由多个2020或2021相加得出

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

int main(){
	int t;
	cin >> t;
	while(t--){
		ll x;
		scanf("%lld",&x);
		if( (x / 2020) >= (x % 2020)){
			puts("YES");
		}else{
			puts("NO");
		}
	}
	return 0;
}

C. Ball in Berland

题目大意

有n个男的m个女的,还有k对关系(a,b)表示第a个男的可以和第b个女的跳舞.现在要求你从k对关系里选出两对不干扰的男女,不干扰即是指同一个人不能出现在两对关系里,问选出两对关系的方案数有多少个

思路

选出两对,直接枚举一条边(u,v)作为选取的一对人,那么现在的问题就是在所有k个关系之中,有多少个关系是和(u,v)无关的,也就是在k跳=条边之中有多少条边连接的两个点既不是u也不是v.这个显然可以求一个补集,也就是求与这两个点有关的边有多少个,再从k个里面去掉就可以了.那么显然也就是两个点的度数之和减一,因为(u,v)这条边会被计入两次.那么枚举答案就可以了.

#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
#define forn(i,x,n) for(int i = x;i <= n;i++)
const int N = 2e5 + 10;
const int NN = 4e5+ 20;
int x[N];
int y[N];
int deg[NN];

int main(){
	int t;cin >> t;
	while(t--){
		int a,b,k;
		scanf("%d %d %d",&a,&b,&k);
		forn(i,0,a+b) deg[i] = 0;
		forn(i,1,k) scanf("%d",&x[i]),++deg[x[i]];
		forn(i,1,k) scanf("%d",&y[i]),++deg[y[i] + a];
		ll n = 0;
		for(int i = 1;i <= k;i++){
			int s = deg[x[i]] + deg[y[i] + a] - 1;
			n += k - s;
		}
		printf("%lld\n",n / 2);
	}
	return 0;
}

D. Cleaning the Phone

题目大意

有n个app,每个app内存是ai,同时每个app根据自己的卸载难度需要花费bi元.问至少卸载m内存的app,最少需要花多少钱.
bi只能为1 或 2

思路

1. 首先,按占用内存从大到小枚举花费为1的app,将其占用的内存和先后push_back到vector<> sum中,即:
[0,a1,a2+a1,a1+a2+a3…] —> [0个花费1的app,一个花费1的app,两个花费1的app…]
方便后续直接二分查找,在满足最低空间要求m时的卸载花费1的app数量
2. 然后,按占用的内存从大到小枚举花费为2的app,题目要求卸载m内存空间,所以,只需要在sum中寻找第一个 ≥ m - cur 的位置,然后计算总共需要卸载的花费2app 和 花费1app 的各自卸载数量,更新res即可
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

const int N  = 2e5 + 10;
int a[N],b[N];

int main(){
	int t;cin >> t;
	while(t--){
		int n,m;
		scanf("%d %d",&n,&m);
		for(int i = 1;i <= n;i++)
			scanf("%d",&a[i]);
		for(int i = 1;i <= n;i++)
			scanf("%d",&b[i]);
		vector<int> a1,a2;
		for(int i = 1;i <= n;i++){
			if(b[i] == 1){
				a1.push_back(a[i]);
			}else{
				a2.push_back(a[i]);
			}
		}
		sort(a1.begin(),a1.end());
		sort(a2.begin(),a2.end());
		reverse(a1.begin(),a1.end());
		reverse(a2.begin(),a2.end());

		vector<ll> sum;
		//先用sum装下花费为 1的app件数 
		sum.push_back(0);
		for(int i = 0;i < a1.size();i++){
			sum.push_back(sum.back()+a1[i]);
		}
		ll cur = 0;
		int res = 1e9;
		// sum是升序,返回第一个 >= m-cur 的值的位置 
		auto it = lower_bound(sum.begin(),sum.end(),m - cur); 
		if(it != sum.end())  //if not found,return end
			res = min( res,(int) (it - sum.begin()) ); //花费为1的可以直接满足 

		//枚举 a2 (花费为2的app中选的件数) 
		for(int i = 0;i < a2.size();i++){
			cur += a2[i];
			// sum是升序,返回第一个 >= m-cur 的值的位置 
			auto it = lower_bound(sum.begin(),sum.end(),m - cur);
			//如果没找到,花费为2的app件数继续增多 
			if(it == sum.end())
				continue;
			//找到了,更新答案 
			// (i+1) * 2 是几个 花费为2的app
			res = min(res,(i + 1) * 2 + (int) (it - sum.begin()));
		}
		printf("%d\n",res == 1e9 ? -1 : res);
	}
	return 0;
}
其余题解可以看这位大佬,好几题是学习过来的

https://www.cnblogs.com/HotPants/p/14328925.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值