文章目录
A - Required Remainder
题解:这个题应该是有很多种解法,这里提供一种比较暴力的方法,我们先把ans去取一个比较大的值,如果这个值大于n的话我们就让他减去一个x,因为减去一个x是对取模结果没有影响的,如果ans小于n的话,直接输出答案即可。
/*Keep on going Never give up*/
#pragma GCC optimize(3,"Ofast","inline")
#include <bits/stdc++.h>
const int maxn = 2e5+10;
const int MaxN = 0x3f3f3f3f;
const int MinN = 0xc0c0c00c;
typedef long long ll;
const int mod = 100000000;
using namespace std;
int main()
{
int t;
cin>>t;
while(t--){
int x,y,n;
cin>>x>>y>>n;
int ans,times=n/x;
while(true){
ans=times*x+y;
times--;
if(ans<=n){
cout<<ans<<endl;
break;
}
}
}
return 0;
}
B - Multiply by 2, divide by 6
题意:这个题,对于一个n,你可以进行两种操作,一种是除以6(必须整除),一种是乘2。
题解:仔细分析一下,3*2=6,所以说,这个二的作用,就是把3变成6,这个步骤一合并,就相当于两步,第一步是把三变成6,第二部是把6变成1.
综上所述,一共有两个过程:
1.直接把6变成1.(耗费1步)
2.把3先变成6,再把6变成1(耗费两步)
/*Keep on going Never give up*/
#pragma GCC optimize(3,"Ofast","inline")
#include <bits/stdc++.h>
const int maxn = 2e5+10;
const int MaxN = 0x3f3f3f3f;
const int MinN = 0xc0c0c00c;
typedef long long ll;
const int mod = 100000000;
using namespace std;
int main()
{
int t;
cin>>t;
while(t--){
int cnt1=0,cnt2=0;
while(n%6==0) n/=6,cnt1++;
while(n%3==0) n/=3,cnt2++;
if(n==1) cout<<cnt1+cnt2*2<<endl;
else cout<<-1<<endl;
}
return 0;
}
C - Move Brackets
题意:一共给你2n个阔号,一半是 ‘(’ ,一半是 ‘)’ 这些括号是乱序的,你可以把某个阔号往最头上或者是最后面放置,问问你最少几次可以把阔号匹配完成。
题解:这个题,你会发现,一个括号往开头放和往结尾放置他的代价是相同的,开阔号的话必然是往开头放,闭括号肯定是往结尾放,那么我么可以选择只动一个类型的阔号,比如说只动闭阔号,我们从头往后遍历,当开阔号数量小于闭阔号数量时,我们选择移动一个闭阔号往右端(同时减去一个闭阔号的数量)。不断记录即可
/*Keep on going Never give up*/
#pragma GCC optimize(3,"Ofast","inline")
#include <bits/stdc++.h>
const int maxn = 2e5+10;
const int MaxN = 0x3f3f3f3f;
const int MinN = 0xc0c0c00c;
typedef long long ll;
const int mod = 100000000;
using namespace std;
string s;
int main()
{
int t;
cin>>t;
while(t--){
int n;
cin>>n;
cin>>s;
int ans1=0,ans2=0;
int sum=0;
for(int i=0;i<n;i++){
if(s[i]=='(') ans1++;
else ans2++;
if(ans2>ans1) sum++,ans2--;
}
cout<<sum<<endl;
}
return 0;
}
D - Zero Remainder Array
思路参考:https://blog.csdn.net/weixin_45483201/article/details/107014826?%3E
代码:
/*Keep on going Never give up*/
#pragma GCC optimize(3,"Ofast","inline")
#include <bits/stdc++.h>
const int maxn = 2e5+10;
const int MaxN = 0x3f3f3f3f;
const int MinN = 0xc0c0c00c;
typedef long long ll;
const int mod = 100000000;
using namespace std;
int a[maxn];
int main()
{
int t;
cin>>t;
while(t--){
int n,k;
cin>>n>>k;
for(int i=0;i<n;i++){
int x;
scanf("%d",&x);
a[i]=x%k;
}
sort(a,a+n,greater<int>());
int cnt=1,imax=1,ans=a[0];
for(int i=1;i<n;i++){
if(!a[i]) break;
if(a[i]==a[i-1]) cnt++;
else cnt=1;
if(cnt>=imax) imax=cnt,ans=a[i];
}
if(ans==0) printf("0\n");
else printf("%lld\n",1ll*k*(imax-1)+k-ans+1);
}
return 0;
}
E1 - Reading Books (easy version)
题意:一共有n本书,看完每本书都有一个花费时间,每本书上都有两个标记,小a是否喜换,小b是否喜换,小a小b是否共同喜换,他们只会阅读自己喜换的书,他们每个人至少阅读k本书,如果他俩共同喜换,那么花费阅读这一本书的时间,会使他俩已经阅读的书总是各加一,求花费最少时间阅读完成k本书的情况,如果无法完成则输出-1。
题解:
那么我们对每本书的情况进行分类
1.小a喜换小b不喜欢。
2.小b喜换小a不喜欢。
3.小a小b都喜欢。
4.小a小b都不喜欢。
这四种情况,可以看出第4种情况的书没有意义,我们直接丢弃即可(因为没人会去看)
那么我们先特判完不成的情况,如果min(第一种情况,第二种情况)+第三种情况,小于k,那么就说明没有那么多书可以让他们看,直接输出-1;
对于可以完成的情况,我们对a,b数组先排序,(a情况时间+b情况时间)=c情况时间。
所以我们可以把(a情况时间+b情况时间)(每次取最小a和b)丢尽优先队列,然后把c情况丢尽优先队列。
然后取有限队列前k个数相加即可
/*Keep on going Never give up*/
#pragma GCC optimize(3,"Ofast","inline")
#include <bits/stdc++.h>
const int maxn = 2e5+10;
const int MaxN = 0x3f3f3f3f;
const int MinN = 0xc0c0c00c;
typedef long long ll;
const int mod = 100000000;
using namespace std;
int a[maxn],b[maxn],c[maxn];
int main()
{
int n,k;
cin>>n>>k;
int cnt1=0,cnt2=0,cnt3=0;
for(int i=0;i<n;i++){
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
if(y==1&&z==0) a[cnt1++]=x;
else if(y==0&&z==1) b[cnt2++]=x;
else if(y==1&&z==1) c[cnt3++]=x;
}
//cout<<cnt1<<cnt2<<cnt3<<endl;
sort(a,a+cnt1);
sort(b,b+cnt2);
sort(c,c+cnt3);
if(cnt3+min(cnt1,cnt2)<k){
cout<<-1<<endl;
return 0;
}
if(cnt3==0){
ll ans=0;
for(int i=0;i<k;i++){
ans+=(ll)a[i]+(ll)b[i];
}
cout<<ans<<endl;
}
else{
ll ans=0;
priority_queue<ll,vector<ll>,greater<ll> >q;
for(int i=0;i<cnt3;i++) q.push((ll)c[i]);
for(int i=0;i<min(cnt1,cnt2);i++){
q.push((ll)a[i]+(ll)b[i]);
}
for(int i=0;i<k;i++){
ans+=q.top();
q.pop();
}
cout<<ans<<endl;
}
return 0;
}