A Required Remainder
题意
给定3个数x,y,n,求一个数k(0<=k<=n),使得k%x=y
思路
设k=
t
×
x
+
y
t\times x+y
t×x+y,也就是找最大的t就行,t=n/x时最大,此时k=(n/x)*x+y
若k>n,则k=k-x;
代码
#include <bits/stdc++.h>
using namespace std;
int main()
{
int n;
cin>>n;
while(n--)
{
int x,y,n,k;
cin>>x>>y>>n;
if(n%x>=y)
{
k=x*(n/x)+y;
}
else if(n%x<y)
{
k=x*(n/x-1)+y;
}
cout<<k<<endl;
}
return 0;
}
B Multiply by 2, divide by 6
题意
给一个数n,可以进行乘2和除6的操作,一共需要多少次操作能得到1,如果不能则输出-1
思路
6=3*2,所以最后的结果能被6整除,则最后的结果是
m
=
2
k
∗
3
k
m=2^k*3^k
m=2k∗3k设
n
=
2
a
∗
3
b
n=2^a*3^b
n=2a∗3b(若还有除2,3以外的因子,或者a>b时,无法使最终结果能被6整除)乘2就是a++,除6就是a–,b–,所以就是直接执行b-a次乘2,b次除6,
代码
#include <bits/stdc++.h>
using namespace std;
int main()
{
int n;
cin >> n;
while (n--)
{
int t;
cin >> t;
int er = 0, san = 0;
while (t % 2 == 0)
{
t /= 2;
er++;
}
while (t % 3 == 0)
{
t /= 3;
san++;
}
if (er > san||t!=1)
{
cout << -1 << endl;
}
else
{
cout<<san-er+san<<endl;
}
}
return 0;
}
C. Move Brackets
题意
给一个长度为n的)和(组成的字符串,求失配的括号对数
思路
用栈来写,遇到(时进栈,若栈为空则失配的括号对数加1
代码
#include <bits/stdc++.h>
using namespace std;
int main()
{
int t;
cin>>t;
while(t--)
{
int n,ans=0;
cin>>n;
stack<char>p;
for(int i=0;i<n;i++)
{
char a;
cin>>a;
if(a=='(') p.push(a);
else
{
if(p.empty()) ans++;
else p.pop();
}
}
cout<<ans<<endl;
}
return 0;
}
D. Zero Remainder Array
题意
给一个长为n的数组和一个k,每次可执行以下两种操作之一
1.a[i]+=x,x++;
2.x++;
经过最少多少次操作后能使得数组里面的每个数都能被k整除
思路
观察数据,暴力肯定会超时,想到用map,保存数组里面每个数需要加的数,必然是0到k-1循环,计算出一共有几个循环,保存最后一次循环的最大数,特殊处理最后一个循环和map为空的情况
代码
#include <bits/stdc++.h>
using namespace std;
map<int, int> zz;
int main()
{
int t;
cin >> t;
while (t--)
{
long long ans=0;
zz.clear();
int n, k, mx = 0, flag = 0;
cin >> n >> k;
for (int i = 0; i < n; i++)
{
int a;
cin >> a;
if (a % k != 0)
{
zz[k - a % k]++;
if (zz[k - a % k] >= mx)
{
if (zz[k - a % k] > mx)
{
flag = k - a % k;
}
else
{
if (k - a % k > flag)
flag = k - a % k;
}
mx = zz[k - a % k];
}
}
}
if (zz.empty())
cout << 0 << endl;
else
{
ans = (mx - 1LL) * k + flag + 1;
cout << ans << endl;
}
}
return 0;
}
E1 Reading Books (easy version)
题意
Alice 和Bob每人要看k本书,看完一本书的时间为t[i],a[i]和b[i]分别表示Alice和Bob是否爱看这本书,若a[i]和b[i]都为1则两人共共看一本书,否则就分开看,a[i]和b[i]都为0时,这本书不能被选,求两人都看完k本书花的最短时间
思路
用贪心的思想,将书分为3种,两人都爱看,Alice爱看,Bob爱看,然后对这三类书都升序排列,当两人都爱看的书中最小的与Alice爱看和Bob爱看的最小的和比较,小于则总时间ans加上两人都爱看的书中最小的,否则就加上Alice爱看和Bob爱看的最小的和,然后去掉已经选过的书,当Alice爱看,Bob爱看的书为都为空时且两人都爱看的书不为空时,只能取两人都爱看的书,当Alice爱看,Bob爱看的书为都不为空且两人都爱看的书都为空时,只能取Alice爱看和Bob爱看的书,若不满足上述条件且选的书不满k时,返回-1
否则返回总时间
代码
#include <bits/stdc++.h>
using namespace std;
int t[210000];
int ans=0;
int at[210000],bt[210000];
bool compare(int a,int b)
{
return a<b;
}
int main()
{
int n,k,st=0,sa=0,sb=0,flag=1;
cin>>n>>k;
for(int i=0;i<n;i++)
{
int p,a1,b1;
cin>>p>>a1>>b1;
if(a1&&b1)
{
t[st++]=p;
}
else if(!a1&&b1)
{
bt[sb++]=p;
}
else if(a1&&!b1)
{
at[sa++]=p;
}
}
sort(t,t+st,compare);
sort(at,at+sa,compare);
sort(bt,bt+sb,compare);
st--,sa--,sb--;
int st1=0,sa1=0,sb1=0;
for(int i=0;i<k;i++)
{
if(((st1<=st&&sa1<=sa&&sb1<=sb)&&(t[st1]<=(at[sa1]+bt[sb1])))||(st1<=st&&!(sa1<=sa&&sb1<=sb)))
{
ans+=t[st1];
st1++;
}
else if(((st1<=st&&sa1<=sa&&sb1<=sb)&&(t[st1]>(at[sa1]+bt[sb1])))||(st1>st&&sa1<=sa&&sb1<=sb))
{
ans+=(at[sa1]+bt[sb1]);
sa1++;
sb1++;
}
else
{
cout<<-1<<endl;
return 0;
}
}
cout<<ans<<endl;
return 0;
}
总结
学到了map的使用,map<type1,type2> a ,在条件有映射关系时使用
优先队列
priority_queue <int,vector,less >q 降序
priority_queue <int,vector,greater >q 升序
E1可以用优先队列简化
取最大最小值(返回值是指向对应元素地址的指针)
max_element
min_element