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;
}