3.22比赛总结

3.22比赛算法题总结

文章目录

原题链接:戳我进入。

前言

首先恭喜我这次考试终于是考到了全班第一!(呜呜呜太不容易了。)

T1

题目描述:白浅妹妹学会了异或运算,现在她开始异或了。
她现在有 n n n 个数字,她必须选中一个数字把它异或上 k k k,其余数字都不变。
现在白浅妹妹想让 n n n 个数字的和变得尽可能的大,请问这些数字的和最多为多大。

很水的一道题,我们只需要算出这个数疑惑后和异或前的差,然后取最大的加上原本的和就行了。(原因:题目中我加粗的那个词。)

(代码过分简单,加上作者太懒,于是决定不写。)

T2

题目描述:白浅妹妹有一个很大的数字,她想让这个数字变得更大(这是作者插入的一句闲话:真就这么喜欢大数啊。)
有两种操作:

  1. 将数字的每一位都增加 1 1 1,如果某一位是 9 9 9,则会增加到 0 0 0。这种操作可以使用无限次。
  2. 将数字的某一位增加 1 1 1,如果某一位是 9 9 9,则会增加到 0 0 0,这种操作至多只能使用一次。
    请问白浅妹妹最多能将数字编程多少。(闲话:这个妹妹不要也罢。)

其实这题依然是灰常的简单啊,我们不难发现:把每一位都加 1 1 1 这样连续操作 10 10 10 次相当于没操作,所以我们只需要先循环从 0 0 0 9 9 9 次,每次进行那么多次操作 1 1 1,然后从高到低选择第一个不是 9 9 9 的数进行操作 2 2 2

(代码依旧很简单,作者依然十分懒……)

闲话:我在考试的时候是直接将高位加到了 9 9 9 然后再执行后面的操作,结果数据点没给我 hack 掉,最后还是我们同学提出来的一组数据会把我 hack 掉。(当然,我们组一共 11 11 11 个人,基本 10 10 10 个人被 hack 掉了,剩下那一个是出数据的。)但是当时已经评测完了,所以就没有加 hack 数据。((:)

T3

题目描述:牛牛上二年级了,今天学习了除法,他想要(闲话:现在我看到这俩词就害怕。)通过若干次除法将一个数字 x x x 变得不超过 y y y
现在牛牛有很多歌除数可以选择,给定一个长度为 n n n 的序列 b b b。表示除数 i i i 的花费是 b i b_i bi,牛牛可以用这个除数把 x x x 变成 ⌊ x i ⌋ \lfloor\cfrac{x}{i}\rfloor ix。每种除数可以使用无限次。
多组询问,每组询问输入两个数 x , y x,y x,y,表示牛牛需要使用若干次除法把 x x x 变得不大于 y y y
对于每一组询问你都要输出一个答案表示求最小话费,保证题目一定有解。(闲话:这除法不学也罢。)

第一眼:哦,背包!

第二眼:哦,不知道是啥……

第三眼:毁灭吧,孩子。

其实这个题的突破口在于你可以连续除以很多个数,所以我们可以用一个比较简单的 DP 来算出要达到除以某个数的效果的最小代价,当然,写代码时为了好写,我们可以反过来:

d p i × j = min ⁡ { d p i × j , d p i + d p j } dp_{i\times j}=\min\{dp_{i\times j},dp_i+dp_j\} dpi×j=min{dpi×j,dpi+dpj}

现在回到初始化:初始化其实很简单,就是除以 i i i 的代价是 a i a_i ai

但这里要提醒一点:在进行上面的 DP 状态转移之前要先从后往前求一遍代价最小值。为啥呢?。

因为你除以 i i i 的目的是 ≤ y \le y y,而你除以比 i i i 大的数也同样可以达到这个效果,所以说它的代价就是后面的最小值。(因为代价要尽可能的小嘛。)

AC 代码:

#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,q,a[100006],c[100006];
signed main()
{
    cin>>n>>q;
    for(int i=1;i<=n;i++)//我直接 dp 和 a 一起合并
    {
        cin>>a[i];
    }
    for(int i=n-1;i>=1;i--)
    {
        a[i]=min(a[i],a[i+1]);
    }
    for(int i=1;i<=1e5;i++)
    {
        for(int j=1;j<=1e5/i;j++)
        {
            a[i*j]=min(a[i*j],a[i]+a[j]);
        }
    }
    for(int i=n-1;i>=1;i--)
    {
        a[i]=min(a[i],a[i+1]);
    }
    a[1]=0;
    while(q--)
    {
        int x,y;
        cin>>x>>y;
        cout<<a[x/(y+1)+1]<<endl;
    }
    return 0;
}

T4

题目描述:对于一个字符串而言,假设有某一个字母只出现过一次,那么我们就称它为“坏子串”。
(例如啥的都省掉了……)
给一个字符串,请问有多少个子串是坏子串。

我不会……(大家自行思考。)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值