Codeforces Round #653 (Div. 3)传送门
题意:在1-n中找到一个k,求符合条件k%x=y的最大k。
题解:在[1,n]中,找到x的最大倍数+y,这样就保证了k%x=y,再判断k+y是否在[1,n]中,若不在只需要再减去一个x。
#pragma GCC optimize(2)
#include
#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;
}
题意:给你一个n,你可以每次进行一次n*2或n/6操作,求最小需要多少次操作才可以使得n变成1,若不能则输出-1
题解:直接暴力模拟,6不是n的因子时就乘2,如果n被除到0就break
#pragma GCC optimize(2)
#include
#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;
}
题意:匹配()括号,如不能匹配成功,则可以进行移动,可移动到任意位置,求需要移动的最小次数
题解:统计左括号(和)右括号,左++右–,当小于0即出现了右括号)但是前面已经没有左括号(可以匹配时才需要移动一次位置。
#pragma GCC optimize(2)
#include
#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;
}
题意:一个长度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
#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;
}
题意: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
#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;
}