美文网首页
19 LatterMay CodeForce 1165Div.3

19 LatterMay CodeForce 1165Div.3

作者: Jfeng666 | 来源:发表于2019-05-20 01:04 被阅读0次

前言

地址:https://vjudge.net/contest/302045#overview

如果是英文劝退……那打扰了,我英语也不行,但英语字典是能带的。有电脑,就用网翻单词然后理解也是可以的吧。
以下是基于对题目的理解,简单提炼的题意,具体数据范围还是要自己看,看完中文题意,会发现还是有一些比较简单的。
至于代码和思路之后再说。

1165A

题意

你被给予了一个n位的十进制数字,没有前导0,每位数字只有0或者1。

你可以对这个数字进行一些操作,对于每个操作,可以将0变成1,或者1变成0,在进行一定的操作后,你可能获得一个前导位0的数字,但这个无关紧要。

现在,你被基于两个整数 0<=y<x<n,你的任务是计算应该执行的最小操作数,使这个数字变成对10^x 取模后,余数为 10^y 的数 ,换句话说,最终获得的数字应该满足 %10^x = 10^y

第一行输入十进制数的位数,x和y
第二行输入十进制数字,左边最高阶

输出最少的操作数

思路

因为只关注对10x取模为10y次方,那么我们只关注,怎么只操作n位数字的后x位,除了对倒数第y+1位要置1外,其他都置为0。我们将后y位数字里面为1的数量记录为time,如果要置1的位置的数字为0则操作数time+1,如果要置1的位置的数字位1,则重复操作,输出time-1.

源代码

#include <iostream>
using namespace std;
char s[200010];
int n,x,y,cunt;
int main()
{
    cin>>n>>y>>x;
    cin>>s;
    cunt=0;
    for (int i=n-y;i<n;i++)
        if (s[i]!='0') cunt++;
    if (s[n-x-1]=='0') cunt++;
    else cunt--;
    cout<<cunt<<endl;
    return 0;
}

1165B

题意

现在有n场比赛的题目,并分别有ai个题目,
主人公每天选择其中一场比赛来做,对于第k天,主人公会去AC比赛里面的k道题目,然后就不做了。
如果第k天选择的这场比赛题目少于k题,那么主人公就不参加了。
请问主人公最多能参加几场比赛。

思路

这题有两个方法,看到另一个同学的方法,感觉我的有些愚钝。
第一种,则是小到大排序,然后遍历数组,每遇到能满足做题数量的比赛,则天数加一。
第二种,则是用数组来记录有n道题的比赛数量,然后遍历一次数组,算是基数排序吧。

源代码,第一种

#include <cstdio>
#include <algorithm>
using namespace std;
int a[200010],n,q;
int main()
{
    scanf("%d",&n);
    for (int i=0;i<n;i++)
        scanf("%d",a+i);
    sort(a,a+n);
    for (int i=0;i<n;i++)
        if (a[i]>q) q++;
    printf("%d\n",q);
    return 0;
}

源代码,第二种

#include <stdio.h>
#include <string.h>
int main()
{
    int n, a[200005] = {0}, i, j, t, count = 0;
    scanf("%d", &n);
    for(i = 0; i < n; i++)
    {
        scanf("%d", &t);
        a[t]++;
    }
    for(i = 1, j = i; i <= n; i++)
    {
        if(j < i)j = i;
        while(0 == a[j] && j <= 200003)j++;
        if(j > 200003)break;
        count++;
        a[j]--;
    }
    printf("%d\n", count);
    
    return 0;
} 

1165C

题意

如果一个字符串的长度是偶数,并且所有在奇数位置的字符和它的下一位的字符不是相同的,那么这个字符串是好字符串。
现在给你一个字符串s,请问最少要删除几个字符才能将它变成好字符串,请将删除的个数k和删除后的字符串输出,如果为空则换行。

思路

这题的方法比较贪心,我们知道像abccd这种字符串,我们只需要删一个就能变成一个好字符串。可以是ab之一,也可以是c。对于连续的重复的字符串,只要它符合好字符串的规则,也就是前一个在偶数位置,后一个在奇数位置,那么就不需要特别处理。当然多与两个便一定要删减了。
我们可以采取贪心的策略,重新组合一个字符串。当我们取奇数位置时,可以随意取,取偶数位置时候,如果和奇数位置相同,则不取。

源代码

#include <cstdio>
char s[200010],res[200010];
int n,len,i;
int main()
{
    scanf("%d%s",&n,s);
    res[0]=s[0];
    for (i=1,len=1;i<n;i++)
        if (s[i]!=s[i-1] || !(len&1) )
            res[len++]=s[i];
    if (len & 1)
        res[--len]=0;
    printf("%d\n%s\n",n-len,res);
    return 0;
}

1165D

题意

我们猜测有这么一个数字x,你被给予了几乎所有这个数字的除数,这个几乎的意思是,除了1和x以外,x的所有因子都已经被给予了,并且我们保证,输入的每一个数字都是不同的,如果这个输入不符合要求,或者找不到这样的数,那么输出-1。

思路

这题主要是问你,如何通过这些数字。
得到X,求有没有重复数字,是否都属于它的因子,有没有漏的因子
分析步骤:
排序
如果数组符合要求,那么这个X必定是最大最小值相乘可得
如果出现1那么必定不符合要求
说了没有重复,有重复当然不符合
只要它符合X,那么一定有n/2组数相乘的结果为X
如果以上都符合,那么我分解质因数,计算所有不同因子的数量cnt,去掉1和X为cnt-2

源代码

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
using namespace std;
long long n,t,a[310];
long long ans()
{
    cin>>n;
    long long cnt=1,sum,q;
    for (int i=0;i<n;i++)
        cin>>a[i];
    sort(a,a+n);
    sum=a[0]*a[n-1];
    q=sum;
    //如果数组符合要求,那么这个X必定是最大最小值相乘可得
    if (a[0]==1) return -1;
    //如果出现1那么必定不符合要求
    for (int i=1;i<n;i++)
        if (a[i]==a[i-1]) return -1;
    //说了没有重复,有重复当然不符合
    for (int i=1,j=n-2;i<=j;i++,j--)
        if (a[i]*a[j] != sum) return -1;
    //只要它符合X,那么一定有n/2组数相乘的结果为X
    for (int i=2,k=0;i*i<=q;i++)
        if (q%i==0) {
            k=2;
            q/=i;
            while (q%i==0)
            {
                k++;
                q/=i;
            }
            cnt*=k;
        }
    if (q>1) cnt*=2;
    //如果以上都符合,那么我分解质因数,计算所有不同因子的数量,去掉1和X为cnt-2
    if (cnt-2 != n) return -1;
    return sum;
}
int main()
{
    cin>>t;
    while (t--)
        cout<<ans()<<endl;
    return 0;
}

1165E

题意

你被给予了两个数组,分别是a和b,它们的长度都为n,我们定义f(l,r)的值为,对所有满足(l<=i<=r)的情况下的ai*bi求和。
对满足(l<=r)的所有情况下f(l,r)的求和,
你可以随意移动数组b里面的数字的位置,然后用求和的结果对998244353取模。
请输出求和得到的最小结果对998244353取模后的值(不是求余数最小,而是结果最小)

思路

我们知道,对于两个元素数量相同的数组,如何排序让它们的各位相乘求和的值最小,那么只能是一个数组正序,一个数组倒序,然后逐个相乘求和。
对于这题,a和b只能移动b数组的顺序,那么其实是一样的,只要b第i大的数字对应a第i小的数字就行了。
但是题目给出了f(l,r)这个函数,并且是所有这个函数相加。不难得到,在n个元素的数组种,对于第i个元素,必定有i*(n-i+1)个区间将这个元素包含在内,也就是说,和第i个元素相关的乘积将出现以上次累加。
对于a这个数组来说,它是不能动的,何不先把这些累计的次数与a里的元素相乘呢。
我们将a内元素和对应累计次数相乘得到的新数组c排正序,b排倒序,再逐位相乘相加,取个模,那就是我们要求的答案了。

源代码

#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
#define MOD 998244353
ll a[200010],b[200010],n,ans,k,q[200010];
int cmp(ll x,ll y) {
    return a[x]>a[y];
}
int main()
{
    cin>>n;
    for (int i=0;i<n;i++)
    {
        cin>>a[i];
        a[i]*=(i+1)*(n-i);
        q[i]=i;
    }
    for (int i=0;i<n;i++)
        cin>>b[i];
    sort(q,q+n,cmp);
    sort(b,b+n);
    ans=0;
    for (int i=0;i<n;i++)
    {
        k=(a[q[i]]%MOD*b[i])%MOD;
        ans=(ans+k)%MOD;
    }
    cout<<ans<<endl;
    return 0;
}

1165F(easy version)

题意

简单版和难版题目的区别只在于数据范围。
主人公Ivan,玩一个电脑游戏,包括很多微交易,可以得到让角色变得更帅的饰品,他想自己的角色看起来更酷,他想利用这些微交易得到饰品,并且他在得到所有东西后才开始玩这个游戏。
每一天早上,Ivan可以赚到游戏里一单位的burle(游戏货币)
有n种微交易,对于每一种微交易的花费,打折时每个饰品花费1单位burle,平时则花费2单位burle。对于第i个饰品,他想要进行ki次交易,订单将在晚上完成。
游戏商店有m次折扣,第j次输入(dj,tj)代表第t种商品在第d天打折。
Ivan想要尽早得到所有的物品,你的任务是计算最少经过多少时间他能买到所有想要数量的饰品,并开始游戏。
……………………有人说还是不懂我简单说下
主角想买一些东西,然后从第一天开始每天领一块钱
平时每件东西是两块,打折日对某些种类当天就一块。
给了你打折日,还有他想买的东西,给好种类和数量了
打折日也说明了日期和种类了
问你最短多少时间内能买完这些东西

思路

对于结果来说,最重要的是天数。如果主角想要n个物品,那么所需要天数必定在n~2n以内,我们只需要找到其中最小的可以买完东西的天数就行了。
对于固定的天数day,我们能接触到的打折活动必定在第day天及之前能接触到。那么对于同一件物品,打折的时间越后,能一次性买的数量越多。我们不妨在这天尽量买足所需数量。但是请注意,在第day天前举办的打折活动,并不能使用day个货币,也就是无法超前消费,那么,对于第day天剩余拥有的货币bday,和第fday天举办的活动(fday<day),我们只能用其中fday个货币,而,bday-fday个货币必定只能用来买2货币一个的物品。
同理,对于第5天和第3天的打折,假设第五天有五个货币,为了满足需求,我买了三个,那么对于第三天的打折,我最多只能买两个,假设对这天打折的需求也是三个,那么剩余一个必定要通过两元一个的原价购买。所以这样的贪心并不影响结果。

源代码

#include <iostream>
#include <algorithm>
using namespace std;
#define maxn 200010
//该算法对于两个范围难度的题都能解决。
int lf, rt, b[maxn];
int ned[maxn], da[maxn], tp[maxn];
int k, p[maxn], n, m;
int cmp(int x, int y) {
    return da[x] < da[y];
}
int min(int a, int b) {
    return a < b ? a : b;
}
bool check(int v) {//测试v块钱能否买完
    for (int i = 1; i <= n; i++)
        b[i] = 1;
    //经过最后打折日的物品在前面打折日则不再购买,因为必定买完,或者剩下的需求没法满足
    int mon = v, cost = 0;
    for (int i = m; i > 0; i--)
        if (b[tp[p[i]]] && da[p[i]] <= v) {
            b[tp[p[i]]] = 0;
            mon = min(mon, da[p[i]]);
            cost += min(mon, ned[tp[p[i]]]);
            mon -= min(mon, ned[tp[p[i]]]);;
        } //只要低于v的折扣都能接触到,但能买的最大数量限制于打折时间和需求。
    return cost + (v - cost) / 2 >= lf;
}
int divide(int lf, int rf) {
    int mid;
    while (lf < rf) {
        mid = (lf + rf) / 2;
        if (check(mid)) rf = mid - 1;
        else lf = mid + 1;
    }
    //为了优化贪心找到答案的次数,我使用二分法。
    return check(rf) ? rf : rf+1;
    //因为退出循环时存在rf=lf和rf=lf-1的可能
}
int main()
{
    cin >> n >> m;
    lf=0;
    for (int i = 1; i <= n; i++){
        cin >> ned[i];
        lf += ned[i];
    } rt = lf * 2;
    for (int i = 1; i <= m; i++) {
        cin >> da[i] >> tp[i];
        p[i] = i;
    }
    sort(p + 1, p + 1 + m, cmp);
    cout << divide(lf, rt) << endl;
    return 0;
}

相关文章

  • 19 LatterMay CodeForce 1165Div.3

    前言 地址:https://vjudge.net/contest/302045#overview 如果是英文劝退…...

  • 社区收集

    简书 habitRpg 开源中国 github nocow codeforce topcoder uva poj ...

  • PolandBall and Forest CodeForce

    PolandBall lives in a forest with his family. There are s...

  • [CodeForce455A]

    题面描述 Alex doesn't like boredom. That's why whenever he ge...

  • 2018-11-18-玄学

    传送门:CodeForce或者:VOJ以下python代码是AC的: 以下C++代码是WA on test 9: ...

  • HDU3183-A Magic Lamp(RMQ-ST)

    A Magic Lamp给出长度不超过1000个数字的数,删除n个数使剩下来的数最小。思路参考:Codeforce...

  • codeforce-Balanced Teams(DP)

    Balanced Teams题意给你n个数,将这n个数最多分成k组,但是每组中的数最大差值不超过5,k组中的人数最...

  • Codeforce - B - Zero Tree (Java

  • 2018-08-31

    题目:codeforce读懂题目就可以了。然而比赛的时候我并没有读懂。。。题目大意:引自CSDN出门时间不确定,求...

  • 2018-12-07-round525

    虽说每场CodeForce都会有题解,但我还是多余的来记录了。A:AB:BC:CD:D虽说有六道题,但是我当时只看...

网友评论

      本文标题:19 LatterMay CodeForce 1165Div.3

      本文链接:https://www.haomeiwen.com/subject/mxoczqtx.html