Codeforces Round #697 (Div. 3)-cf补题
Codeforces Round #697 (Div. 3)
https://codeforces.com/contest/1475
D. Cleaning the Phone
个人感觉D题比较难一点,也可能是当时没有想清楚!!
题意就是如何取尽可能多的ai并且bi尽可能小,(当时没有注意到bi的取值: 1=<bi<=2),因为b只有两种取值:1和2,那么就只有三种最优方案,即:只取bi为1的、只取bi为2的、两个都取。
接下来就是将bi为1和2的两种ai分类排序,将bi为2的ai序列求前缀和。然后遍历bi为1的ai,在每一次取完后判断此时取bi为2是否为最佳,直到取bi为1的ai总和大于等于m为止,最后再和只取bi为2的情况比较一下即可。
Code
#include<bits/stdc++.h>
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
using namespace std;
const int inf=0x3f3f3f3f;
typedef long long ll;
const int N=2e5+7;
const ll mod=1e9+7;
bool cmp(ll x,ll y){
return x>y;
}
ll a[N],b[N],f[N];
int main(){
IO;
int t=1;
cin>>t;
while(t--){
int n;
ll m;
cin>>n>>m;
ll sum=0;
int ans=1e9;
vector<ll>x[3];
for (int i = 1; i <= n; ++i)
{
cin>>a[i];
}
for (int i = 1; i <= n; ++i)
{
cin>>b[i];
x[b[i]].push_back(a[i]);
}
sort(x[1].begin(),x[1].end(),cmp);
sort(x[2].begin(),x[2].end(),cmp);
int len1=int(x[1].size()),len2=int(x[2].size());
for (int i = 0; i < len2; ++i)
{
if(!i)f[i]=x[2][i];
else f[i]=f[i-1]+x[2][i];
}
for (int i = 0; i < len1; ++i)
{
sum+=x[1][i];
if(sum>=m){
ans=min((i+1),ans);
break;
}
ll k=m-sum;
int pos=lower_bound(f,f+len2,k)-f;
if(pos==len2)continue;
ans=min(ans,(i+1+(pos+1)*2));
}
int pos=lower_bound(f,f+len2,m)-f;
if(pos<len2){
ans=min(ans,(pos+1)*2);
}
if(ans==1e9)cout<<-1<<endl;
else cout<<ans<<endl;
}
return 0;
}
F. Unusual Matrix
个人感觉这一题不该放到F题,昨晚见到F题的时候只剩十分钟了!
题意要求矩阵a能否通过整行和整列异或可以得到矩阵b
因为元素只有0和1,所以直接将a的第一行进行相应异或变成b的第一行,然后根据第一行各列的异或情况在每行进行相同操作,最后判断a是否与b相同(需要特判一下a中如果整行与b不同也满足要求)
Code
#include<bits/stdc++.h>
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
using namespace std;
const int inf=0x3f3f3f3f;
typedef long long ll;
const int N=2e5+7;
const ll mod=1e9+7;
string x[1007],y[1007];
int a[1007];
int main(){
IO;
int t=1;
cin>>t;
while(t--){
memset(a,0,sizeof(a));
int n;
cin>>n;
for (int i = 0; i < n; ++i)
{
cin>>x[i];
}
for (int i = 0; i < n; ++i)
{
cin>>y[i];
}
for (int i = 0; i < n; ++i)
{
if(x[0][i]==y[0][i])continue;
a[i]=1;
}
for (int i = 0; i < n; ++i)
{
for (int j = 0; j < n; ++j)
{
x[i][j]^=a[j];
}
}int flag=0;
for (int i = 0; i < n; ++i)
{
for (int j = 0; j < n; ++j)
{
if(x[i][j]!=y[i][j]){
flag++;
}
}if(flag){
if(flag==n){
flag=0;
continue;
}else break;
}
}if(!flag)cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
return 0;
}
G. Strange Beauty
找到最大的序列其中任意两个数都存在整除关系,可以考虑从大到小找,每个数都从它的倍数中找到出现次数最大的,然后往下递推。因为每一个数都是从它的倍数中取得最大值,从而保证得到的序列中每一个大数都是小数的倍数。
Code
#include<bits/stdc++.h>
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
using namespace std;
const int inf=0x3f3f3f3f;
typedef long long ll;
const int N=2e5+7;
const ll mod=1e9+7;
int a[N],dp[N];
map<int,int>mp;
int main(){
IO;
int t=1;
cin>>t;
while(t--){
int n;
cin>>n;
mp.clear();
for (int i = 1; i <= n; ++i)
{
cin>>a[i];
mp[a[i]]++;
}
for (int i = 2e5; i > 0; --i)
{
dp[i]=mp[i];
for (int j = i*2; j <= 2e5; j+=i)
{
dp[i]=max(dp[j]+mp[i],dp[i]);
}
}int ans=1e9;
for (int i = 1; i < 2e5+1; ++i)
{
ans=min(ans,n-dp[i]);
mp[i]=0;
}cout<<ans<<endl;
}
return 0;
}
加油!!!
Code will change the world !

浙公网安备 33010602011771号