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

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=2k3k
n = 2 a ∗ 3 b n=2^a*3^b n=2a3b(若还有除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

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值