模拟赛二补题报告

声明:本次模拟赛题目均为统一内容,若在“题目大意”栏中有和他人相同的文字,属正常现象,非抄袭!!!

不出所料,我写完这个报告已经是在十月二号的凌晨了。小睡一会,写一写国庆的数学作业。爬起来,继续上课!
不说废话,来,报告呈上!


一、题目报告

比赛共四题。其中第一题AC,第二题70分,其余零分。赛后补四题,AK。

二、赛中情况

比赛中第一题样例全过,后续在思考(实际上是同学说出来的) 后改进代码,AC。第二题直接使用暴力模拟,样例全过,但是没有考虑时间,30%数据TLE,第三题想了得有半个小时,根本想不出来怎么做,就骗了点分,后来才知道要用差分和两次前缀/后缀和来做。就是有个大问题。没 写 输 出 (哎呀,脑子啊)至于第四题,写的时候就剩最后10分钟了,那是一点思路都没有,直接把背包问题忘了,啥代码也没写提交了。

三、题解报告

T1:人员借调

题目大意

某人在 A 地工作能力非常出众,B 地的领导想借调某人帮忙处理件事情,某人处理第件的耗时为分钟。
正常借调的过程为小可从 A 地到 B 地进行jiaqilai处理,处理结束之后回到 A 地。
但是由于某人能力过于突出,如果某人在 B 地待连续大于等于240分钟时,A 地领导会非常的不高兴,将强制把某人留在 A 地7天(10080分钟),7天结束后小可可以继续留在 A 地正常工作或者继续前往B 地帮忙处理事情。
于是,某人有了一个对策,在分钟快到的时候就此 B 地回到 A 地,然后再去 B 地,这样的话分钟就会重新计时。注意:从 A 地往返一次 B 地会耗时分钟(这个时间不计算到待在 B 地的时间)。
现在某人从 A 地准备出发,需要在 B 地处理完所有事,然后回到 A 地正常的工作。
注意: 件事情的不可以打乱,并且开始处理一个事情时,这个事情必须处理完才可以继续后面的内容(无论是回 A 地还是继续处理后面的事情)。
请问某人至少需要多少分钟?

赛时思路

见正确思路,与正确思路一致。

题目解析及正确思路

连续累加某人做事的时间,如果不超过240分钟,就继续累加,合并去做。如果已经超过了240分钟,就要考虑是往返重置240分钟计时时间断还是全部做完后回A地强制停留(坐牢)时间长了。取最短的时间,就是答案。

STD

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
int n,a[1005],sum=0;
int main()
{
    cin>>n;
    for(int i=1; i<=n; i++)
    {
        cin>>a[i];
    }
    int i=1,m=0;
    while(i<=n)
    {
        m+=a[i];
        i++;
        if(m>=240)
        {
            sum+=10480+m;
            m=0;
        }
        else
        {
            while(m+a[i]<240&&i<=n)
            {
                m+=a[i++];
            }
            sum+=m+400;
        }
        m=0;
    }
    int sum2=0;
    for(int i=1; i<=n; i++)
    {
        sum2+=a[i];
    }
    if(sum2>=240) sum2+=10480;
    else sum2+=400;
    cout<<min(sum,sum2);
    return 0;
}

T2:计算

题目大意

计算需要使用到三个整数:m,n,k
计算条件如下(设x为满足计算条件的数字):
1:m≤x≤n;
2: 在十进制下所有位上的数字之和为k。
根据计算条件得到的x可能会很多,请输出十进制下所有位上的数字的积最大的那个(如果有多个积相等,则输出x最小的那个)
数据保证有解!

赛时思路

能怎么办?把打表忘了。直接模拟,30%测试点TLE。

题目解析及正确思路

模拟必定会有部分TLE,所有要先打一个表,存好各种数据,直接for循环找就行了。

STD

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int s[5000005],f[5000005];
int main()
{
    f[0]=1;
    for(int i=1; i<=5000000; i++)
    {
        s[i]=s[i/10]+i%10;
        f[i]=f[i/10]*(i%10);
    }
    f[0]=-1;
    int t;
    cin>>t;
    while(t--)
    {
        int m,n,k,ans=0;
        cin>>m>>n>>k;
        for(int i=m; i<=n; i++)
        {
            if(s[i]==k&&f[i]>f[ans]) ans=i;
        }
        cout<<ans<<" "<<f[ans]<<endl;
    }
    return 0;
}

T3:智能公交

题目大意

马路上总共有n个公交站台,编号从 1,2,…,n。有一辆智能公交车会在这n个站台之间穿梭。
如果智能公交上没有乘客,那么智能公交就会停靠在x站台。
例如,有人想从a站台到b站台,那么公交车会先从第x个站台跑到a站台,然后再从a站台跑到b站台,然后再回到x站台停下。智能公交总共行走了
|x-a|+|a-b|+|b-x|的距离。
现在有m个人要依次乘坐智能公交,每个人都会等待智能公交停在x站台之后准备乘坐公交。现在已知第i个人都是从ai站台到bi站台。请你计算x,使得智能公交移动距离最短。最终输出x和最短的距离,x若有多个,输出最小的一个。

赛时思路

实在想不起来用前缀和和差分了。我也不知道我当时整了个什么玩意,反正最后没写输出,分都没有骗到。

题目解析及正确思路

我们假设sum表示公交车停靠在x的总移动距离,那么给定a,b的时候,相当于将整个数组全部加 2*|a-b|,并且将a-1到1的位置额外加一个公差为 2 的等差数列;同理,将b+1到n的位置加一个公差为2的等差数列。
考虑用差分来维护区间加法,等差数列加法,即可解决此题。

STD

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
int n,m,a,b;
long long ans=1e18,pos,sum=0
int main() {
    cin>>n>>m;
    long long q1[n+2],q2[n+2],c1[n+2],c2[n+2];
    while(m--) {
        cin>>a>>b;
        q1[a-1]+=2;
        c1[b+1]+=2;
        sum+=(b-a)*2;
    }
    for(int i=n; i>=1; i--) {
        q1[i]+=q1[i+1];
        q2[i]=q2[i+1]+q1[i];
    }
    for(int i=1; i<=n; i++) {
        c1[i]+=c1[i-1];
        c2[i]+=c2[i-1]+c1[i];
        if(c2[i]+q2[i]<ans) {
            pos=i;
            ans=c2+p2;
        }
    }
    cout<<pos<<" "<<ans+sum;
    return 0;
}

T4:异或和

题目大意

多个集合中总共有n个数字,并且已知每个数字的大小ai和属于某个集合 bi。
在一个集合中选择一个数字,收益为这个数字的大小,选择多个数字,收益为这些数字的异或和。总收益为每个集合的收益之和。注意:最多从中选择m(m≤n)个数字,使这些数字总收益最大。

赛时思路

根本就没有什么想法,最后10分钟也想不出来什么,啥代码也没写,直接就提交了。

题目解析及正确思路

其实这个题可以转换为分组背包。开成三维数组会超内存,故可以之用二维数组,但每次使用后清空。这样就需要再开一个数组num[i][j]表示第i组选 个j数最大的异或值。每一组结束 dp 预处理操作后存入 num 中,最后使用一个分组背包即可得到最大异或值。但是要注意,在每一组 dp 预处理时,i 应循环到组中元素的个数而不是n否则会超时。 由于n的总值仍是2000,所以操作时组和i的循环次数总和仍为2000,时间复杂度不变。
备注:最后使用分组背包的话就是 O(n2),如果循环条件没写好(比如使用memset),那就是O(n3

STD

#include <bits/stdc++.h>
using namespace std;
int n,m,dp[2005][2050],num[2005][2005],dpp[2050],zz[2005];
vector<int> ve[2005];
int main() {
    cin >> n >> m;
    for (int i = 1; i <= n; i++) {
        int x, y;
        cin >> x >> y;
        ve[y].push_back(x);
        zz[y]++;
    }
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= 2047; j++) {
            dp[i][j] = 1e9;
        }
    }
    for (int zu = 1; zu <= 2000; zu++) {
        if (zz[zu] != 0) dp[1][ve[zu][0]] = 1;

        for (int i = 2; i <= zz[zu]; i++) {
            dp[i][ve[zu][i - 1]] = 1;
            for (int j = 1; j <= 2047; j++) {
                if (dp[i - 1][j] != 1e9) {
                    dp[i][j] = min(dp[i][j], dp[i - 1][j]);
                    dp[i][j ^ ve[zu][i - 1]] =min(dp[i - 1][j] + 1, dp[i][j ^ ve[zu][i - 1]]);
                }
            }
        }
        for (int j = 1; j <= 2047; j++) {
            if (dp[zz[zu]][j] != 1e9) num[zu][dp[zz[zu]][j]] = max(num[zu][dp[zz[zu]][j]],
                        j);
        }
        for (int i = 1; i <= zz[zu]; i++) {
            for (int j = 1; j <= 2047; j++) {
                dp[i][j] = 1e9;
            }
        }
    }
    for (int i = 1; i <= 2000; i++) {
        for (int j = m; j >= 1; j--) {
            for (int k = 1; k <= zz[i]; k++) {
                if (j >= k) dpp[j] = max(dpp[j], dpp[j - k] + num[i][k]);

            }
        }
    }
    cout << dpp[m];
    return 0;
}

四、考后总结

本次考试,成绩比昨天进步了110分(真吉利),但出现了无法灵活运用知识点,如第三题没想起来使用前缀和与差分,已经无法解决混合知识点问题的问题,如第四题没有想起抽象为分组背包,以后要勤背知识点,多做练习题。
The End.


五、一点没用的闲聊和图片

闲聊

其实到这里补题报告已经写完了。但还是想和大家聊一聊。
写到这里已经是2023年10月2日01:15:27了。再这么熬下去真的会猝死啊。但又有什么办法呢。作业是真多啊,不熬夜真的写不完啊。
今天写几张数学卷子吧,一点半睡七点半起,压缩一些早上时间,睡六个小时,应该够了。
不要问我为什么不用删除线,问就是Markdown出BUG了,显示不出来。

这些图片没有营养,千万别看!!!

最后也是给大家几张我喜欢的人的图片吧
这些图片没有营养,千万别看!!!
其实没有营养,不用看
其实没有营养,不用看
其实没有营养,不用看
其实没有营养,不用看
其实没有营养,不用看
其实没有营养,不用看

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值