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