Codeforces Round #653 (Div. 3)A-B-C-D-E1

Codeforces Round #653 (Div. 3)传送门

A.Required Remainder

题意:在1-n中找到一个k,求符合条件k%x=y的最大k。
题解:在[1,n]中,找到x的最大倍数+y,这样就保证了k%x=y,再判断k+y是否在[1,n]中,若不在只需要再减去一个x。

#pragma GCC optimize(2)
#include <bits/stdc++.h>
#define ll long long
#define endl  '\n'
using namespace std;
int main()
{
    ios::sync_with_stdio(0);cin.tie(0), cout.tie(0);
    int t;cin>>t;
    while(t--)
    {
      	ll ans=0,x,y,n;cin>>x>>y>>n;
      	ans=n/x*x+y;
      	if(ans>n)ans-=x;  
      	cout<<ans<<endl;
    }
    return 0;
}

B. Multiply by 2, divide by 6

题意:给你一个n,你可以每次进行一次n*2或n/6操作,求最小需要多少次操作才可以使得n变成1,若不能则输出-1
题解:直接暴力模拟,6不是n的因子时就乘2,如果n被除到0就break

#pragma GCC optimize(2)
#include <bits/stdc++.h>
#define ll long long
#define endl  '\n'
using namespace std;
int main()
{
    ios::sync_with_stdio(0);cin.tie(0), cout.tie(0);
    int t;cin>>t;
    while(t--)
    {
      ll n,ans=0;cin>>n;
      int f=0;
	  while(n>=1)
	  {
		  	if(n==1){
		  		f=1;break;
		    }
		  	if(n%6!=0)n*=2;
		  	else n/=6;
		  		ans++;
	  }
	  	if(f)cout<<ans<<endl;
	  	else cout<<-1<<endl;
    }
    return 0;
}

C. Move Brackets

题意:匹配()括号,如不能匹配成功,则可以进行移动,可移动到任意位置,求需要移动的最小次数
题解:统计左括号(和)右括号,左++右–,当小于0即出现了右括号)但是前面已经没有左括号(可以匹配时才需要移动一次位置。

#pragma GCC optimize(2)
#include <bits/stdc++.h>
#define ll long long
#define endl  '\n'
using namespace std;
int main()
{
    ios::sync_with_stdio(0);cin.tie(0), cout.tie(0);
    int t;cin>>t;
    while(t--)
    {
      	ll n,k=0,ans=0;cin>>n;
      	string s;cin>>s;
      	for(int i=0;i<n;i++)
      	{
      		if(s[i]=='(')k++;
			else {
				if(k)k--;
				else ans++;
			}	
		}
		cout<<ans<<endl;
    }
    return 0;
}

D. Zero Remainder Array

题意:一个长度n的a数组,x从x=0开始不断递增加1,可以进行操作①从数组a中挑一个a[i]=a[i]+x,然后x递增1,操作②不挑数组a的元素加x,x直接递增1。求你最少需要进行多少次操作使得数组a中的所有元素变成k的倍数。
题解:因为x是不断递增的,且知道x累加到≥k时其实对数组a中每个元素a[i]变成k的倍数的贡献只有x%k,故此处可以看成x不断的从[0,k-1]循环,直接用map统计数组a中每个元素a[i]最少还需要加多少才成变成k的倍数,选出map中的最大值-1即是需要循环的次数,再加上最后一次未完整循环的最大值。
注意:会卡数组,会卡unordered_map,所以需要用map

#pragma GCC optimize(2)
#include <bits/stdc++.h>
#define ll long long
#define _for(i,a,b) for(int i = (a);i<(b);i++)
#define endl  '\n'
using namespace std;
int main()
{
    ios::sync_with_stdio(0);cin.tie(0), cout.tie(0);
    int t;cin>>t;
    while(t--)
    {
      ll n,k,x;cin>>n>>k;
      map<ll,ll>a;
      ll mx=0,l=0;
	  for(ll i=0;i<n;i++)
	  {
	  	cin>>x;
	  	if(k-x%k!=k){
	  		a[k-x%k]++;
	  		if(mx<a[k-x%k])
	  		{
	  			mx=a[k-x%k];
	  			l=k-x%k;
			}
			else if(mx==a[k-x%k])l=max(l,k-x%k);
		  }
	  }
	  if(mx!=0)
	  cout<<(mx-1)*k+l+1<<endl;
	  else cout<<0<<endl;	
    }
    return 0;
}

E1. Reading Books (easy version)

题意:Alice 和Bob 两人都需要看k本书,一共有n本书,看完每个本需要用t[i]
时间,a[i]和b[i],等于1时表示喜欢这本书,等于0时表示不喜欢这本书,Alice 和Bob 两人只看自己喜欢的书,且两人每次只能选一本书读,若其中一人喜欢一人不喜欢,那就只有一人读。求最少需要多少时间使得Alice 和Bob 两人都读完k本书。
题解:分别统计a[i]=b[i]=1,a[i]=0和b[i]=1,a[i]=1和b[i]=0。把a[i]=0和b[i]=1,a[i]=1和b[i]=0合并,相当于变成a[i]=b[i]=1,再加入到a[i]=b[i]=1中,然后用sort,前缀和选出前面k个小的。
需要注意的是,a[i]=0和b[i]=1,a[i]=1和b[i]=0这两种情况不一定出现相同次数,所以能合并成a[i]=b[i]=1的对数是a[i]=0和b[i]=1,a[i]=1和b[i]=0情况的较小值。

#pragma GCC optimize(2)
#include <bits/stdc++.h>
#define ll long long
#define endl  '\n'
using namespace std;
int main()
{
    ios::sync_with_stdio(0);cin.tie(0), cout.tie(0);
   ll n,k;cin>>n>>k;
   vector<ll>a,b,c;
   for(ll i=0;i<n;i++)
   {
   		ll t,x,y;cin>>t>>x>>y;
   		if(x==1&&y==1)
   			a.push_back(t);	
		if(x==1&&y==0)
			b.push_back(t);
		if(x==0&&y==1)
			c.push_back(t);
   }
   if(b.size()>c.size()) swap(b,c);
   if(a.size()+b.size()<k) cout<<-1;
   else {
	   sort(b.begin(),b.end());
	   sort(c.begin(),c.end());
	  for(ll i=0;i<b.size();i++)
	  	b[i]+=c[i]; 
	   sort(b.begin(),b.end());
	   for(ll i=0;i<b.size();i++)
	   	a.push_back(b[i]);
	   sort(a.begin(),a.end());
	   	ll ans=0;
	   	for(ll i=0;i<k;i++)
	   	ans+=a[i];
	   	cout<<ans;
   }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章