2019.10.24模拟赛赛后总结

本文原创,如果有不到位的地方欢迎通过右下角的按钮私信我!

A.Icow Player

题目描述

被无止境的农活压榨得筋疲力尽后,Farmer John打算用他在MP3播放器市场新买的iCow来听些音乐,放松一下。FJ的iCow里存了N(1 <= N <= 1,000)首曲子,按1..N依次编号。至于曲子播放的顺序,则是按一个Farmer John自己设计的算法来决定:
* 第i首曲子有一个初始权值R_i(1 <= R_i <= 10,000)。
* 当一首曲子播放完毕,接下来播放的将是所有曲子中权值最大的那首(如果有两首或多首曲子的权值相同,那么这些曲子中编号最小的那首会被选中)。
* 一首曲子在播放结束后,它的权值会被平均地分给其他N-1首曲子,它本身的权值清零。
* 如果一首曲子的权值无法被平均分配(也就是说,无法被N-1整除),那么被N-1除的余数部分将会以1为单位,顺次分配给排名靠前的曲子(也就是说,顺序为曲目1、曲目2...依次下去。当然,刚播放过的那首曲子需要被跳过),直到多出的部分被分配完。
在选定的下一首曲子播放完毕后,这个算法再次被执行,调整曲子的权值,并选出再接下来播放的曲目。
请你计算一下,按FJ的算法,最先播放的T(1 <= T <= 1000)首曲子分别是哪些。

输入

第1行: 2个用空格隔开的整数:N 和 T
第2..N+1行: 第i+1行为1个整数:R_i

输出

第1..T行: 第i行为1个整数,表示iCow播放的第i首曲子

样例输入

3 4
10
8
11

样例输出

3
1
2
3

题目总结

这道题拿到之后最先想到的就是模拟,于是我大致把程序拆分成了个部分——输入、播放、分配和输出。其中输入就不再赘述,播放部分每次播放权值最大的一首,所以每次都要找到权值最大的一首歌。在这里我犯了一个非常严重的错误——对所有数据进行排序,而且我担心复杂度过高,于是以n为周期每n次播放排序一次,这也是我后面只得10分的原因。
错误部分代码:

    for(int i=1;i<=t;i++){
        if(i%n==1)sort(a+1,a+1+n,cmp);//每n次播放排序一次
        if(i%n==0)cout<<a[n].bh<<endl;//防止出现n倍数次循环出现下标为零的情况
        else cout<<a[i%n].bh<<endl;
        int sum1=a[i%n==0?n:i%n].r/n-1;//下面是分配部分代码 ,一堆玄学三目运算符
        int sum2=a[i%n==0?n:i%n].r%n-1;
        for(int j=1;j<=n;j++){
            if(j==i%n==0?n:i%n)continue;
            a[j].r+=sum1;
        }
        s:;
        if(sum2>n){
            for(int j=1;j<=n;j++){
                if(j==i%n==0?n:i%n)continue;
                a[j].r++;
            }
            sum2-=n-1;
            goto s;
        }
        for(int j=1;j<=sum2;j++){
                if(j==i%n==0?n:i%n)continue;
                a[j].r++;
            }
    }

AC代码:

#include<bits/stdc++.h>
using?namespace?std;
struct?node{
????int?v;
????int?d;
}?a[1005];
//结构体方便比较权值大小,也方便查找数据的编号;
int?main(){
    int?n,t;
???int?i,r,max,num,k,id;
???cin>>n>>t;
???for(i=1;?i<=n;?i++){
???    cin>>a[i].v;
??????a[i].d=i;
???}
???while(t--){
??????max=0;
        for(i=1;?i<=n;?i++)? //比较权值的大小
??????    if(a[i].v>max){
?????????    max=a[i].v;
????????????id=a[i].d;
?????????}
??????cout<<id<<endl;//每次输出权值最大的歌曲的编号
??????num=a[id].v;//分配部分
??????k=num/(n-1); //平分播放了的歌曲的权值;
????? r=num%(n-1);//除不尽小数部分化为整数1分给最近的歌曲权值;
??????a[id].v=0;
??????for(i=1;?i<=n;?i++){
??????    if(i!=id)a[i].v+=k;???????
??????}
??????for(i=1;?i<=r;?i++){
?????????if(i==id)
?????????    r++;
?????????else
??????????? a[i].v+=1;
??????}
????}
????return?0;
}

B.Costume

题目描述

万圣节又到了!Farmer John打算带他的奶牛去参加一个化装晚会,但是,FJ只做了一套能容下两头总长不超过S(1 <= S <= 1,000,000)的牛的恐怖服装。FJ养了N(2 <= N <= 20,000)头按1..N顺序编号的奶牛,编号为i的奶牛的长度为L_i(1 <= L_i <= 1,000,000)。如果两头奶牛的总长度不超过S,那么她们就能穿下这套服装。
FJ想知道,如果他想选择两头不同的奶牛来穿这套衣服,一共有多少种满足条件的方案。

输入

第1行: 2个用空格隔开的整数:N 和 S
第2..N+1行: 第i+1为1个整数:L_i

输出

第1行: 输出1个整数,表示FJ可选择的所有方案数。注意奶牛顺序不同的两种 方案是被视为相同的。

样例输入

4 6
3
5
2
1

样例输出

4

提示

【输出说明】 4种选择分别为:奶牛1和奶牛3;奶牛1和奶牛4;奶牛2和奶牛4;奶牛3和奶牛4。

题目总结

看大佬们的都是做的分治,但数据规模只有n<=20,000,所以直接暴力枚举所有可能然后判断可不可以装下就行了
AC代码:

#include<bits/stdc++.h>
using namespace std;
int n,s,l[20001],ans;
int main(){
    freopen("costume.in","r",stdin);
    freopen("costume.out","w",stdout);
    cin>>n>>s;
    for(int i=1;i<=n;i++){
        cin>>l[i];
    }
    for(int i=1;i<n;i++){
        for(int j=i+1;j<=n;j++){
            if(l[i]+l[j]<=s)ans++;
        }
    }
    cout<<ans;
    return 0;
}

C.Contest

题目描述

FJ的N(1 <= N <= 100)头奶牛们最近参加了场程序设计竞赛:)。在赛场上,奶牛们按1..N依次编号。每头奶牛的编程能力不尽相同,并且没有哪两头奶牛的水平不相上下,也就是说,奶牛们的编程能力有明确的排名。
整个比赛被分成了若干轮,每一轮是两头指定编号的奶牛的对决。如果编号为A的奶牛的编程能力强于编号为B的奶牛(1 <= A <= N; 1 <= B <= N; A != B),那么她们的对决中,编号为A的奶牛总是能胜出。
FJ想知道奶牛们编程能力的具体排名,于是他找来了奶牛们所有M(1 <= M <= 4,500)轮比赛的结果,希望你能根据这些信息,推断出尽可能多的奶牛的编程能力排名。比赛结果保证不会自相矛盾。

输入

第1行: 2个用空格隔开的整数:N 和 M
第2..M+1行: 每行为2个用空格隔开的整数A、B,描述了参加某一轮比赛的奶牛的编号,以及结果(编号为A,即为每行的第一个数的奶牛为胜者)

输出

第1行: 输出1个整数,表示排名可以确定的奶牛的数目

样例输入

5 5
4 3
4 2
3 2
1 2
2 5

样例输出

2

提示

【输出说明】 编号为2的奶牛输给了编号为1、3、4的奶牛,也就是说她的水平比这3头奶 牛都差。而编号为5的奶牛又输在了她的手下,也就是说,她的水平比编号为5的 奶牛强一些。于是,编号为2的奶牛的排名必然为第4,编号为5的奶牛的水平必 然最差。其他3头奶牛的排名仍无法确定。

题目总结

这道题我直接全做错了然后卡了10分
我的错误思路是:如果有了a,b比赛的结果,就可以判断a,b的关系,如果一个人可以和其他n-1人的关系都确定,答案数就加一
错误代码:

#include<bits/stdc++.h>
using namespace std;
int win[101][101],n,m,a,b,ans,flag;
int main(){
    freopen("contest.in","r",stdin);
    freopen("contest.out","w",stdout);
    cin>>n>>m;
    for(int i=1;i<=m;i++){
        cin>>a>>b;
        win[a][b]=win[b][a]=1;
    }
    for(int i=1;i<=n;i++){
        flag=0;
        for(int j=i+1;j<=n;j++){
            if(win[i][j]==0){
                flag=1;break;
            }
        }
        if(flag==0)ans++;
    }
    cout<<ans;
    return 0;
}

正确的做法是用Floyed,用一个二维数组存储比赛结果,然后三重循环枚举k、i、j,判断i==j?,然后判断win[i][k]是否为i,win[k][j]是否为k,如果全部满足的就把win[i][j]和win[j][i]设为i,最后判断是不是和其他人都比赛过了,如果是的话就答案数增加
AC代码:

#include<iostream>
#include<cstdio>
using namespace std;
int a,b,n,m,f[101][101],ans;
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++){
        scanf("%d%d",&a,&b);
        f[a][b]=1;
    }
    for(int k=1;k<=n;k++)
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
              f[i][j]=f[i][j]|f[i][k]&f[k][j];
    for(int i=1;i<=n;i++){
        int gg=1;
        for(int j=1;j<=n;j++)
        if(i==j)continue;else
         gg=gg&(f[i][j]|f[j][i]);
         ans+=gg;
    }
    printf("%d\n",ans);
}

D.Cowrun

题目描述

奶牛们打算通过锻炼来培养自己的运动细胞,作为其中的一员,贝茜选择的运动方式是每天进行N(1 <= N <= 10,000)分钟的晨跑。在每分钟的开始,贝茜会选择下一分钟是用来跑步还是休息。
贝茜的体力限制了她跑步的距离。更具体地,如果贝茜选择在第i分钟内跑步,她可以在这一分钟内跑D_i(1 <= D_i <= 1,000)米,并且她的疲劳度会增加1。不过,无论何时贝茜的疲劳度都不能超过M(1 <= M <= 500)。如果贝茜选择休息,那么她的疲劳度就会每分钟减少1,但她必须休息到疲劳度恢复到0为止。在疲劳度为0时休息的话,疲劳度不会再变动。晨跑开始时,贝茜的疲劳度为0。
还有,在N分钟的锻炼结束时,贝茜的疲劳度也必须恢复到0,否则她将没有足够的精力来对付这一整天中剩下的事情。
请你计算一下,贝茜最多能跑多少米。

输入

第1行: 2个用空格隔开的整数:N 和 M
第2..N+1行: 第i+1为1个整数:D_i

输出

第1行: 输出1个整数,表示在满足所有限制条件的情况下,贝茜能跑的最大距离

样例输入

5 2
5
3
4
2
10

样例输出

9

提示

【输出说明】 贝茜在第1分钟内选择跑步(跑了5米),在第2分钟内休息,在第3分钟内跑 步(跑了4米),剩余的时间都用来休息。因为在晨跑结束时贝茜的疲劳度必须 为0,所以她不能在第5分钟内选择跑步。

题目总结

这道题我根本就没看懂
AC代码:

#include<bits/stdc++.h>
#define MAXN 11111
#define MAXM 555
#define INF 1000000007
using namespace std;
int dp[MAXN][MAXM];
int a[MAXN];
int n, m;
int main()
{
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
    for(int i = 1; i <= n; i++)
    {
        dp[i][0] = dp[i - 1][0];
        for(int j = 1; j <= m; j++)
        {
            if(i >= j) dp[i][0] = max(dp[i][0], dp[i - j][j]);
            dp[i][j] = max(dp[i - 1][j - 1] + a[i], dp[i][j]);
        }
    }
    printf("%d\n", dp[n][0]);
    return 0;
}

原文地址:https://www.cnblogs.com/MikeC/p/11827800.html

时间: 2024-10-18 23:00:54

2019.10.24模拟赛赛后总结的相关文章

2019.10.24模拟赛

T1 古代龙人的谜题 Mark Douglas 是一名调查员.他接受了「调查古代龙人」的任务.经过千辛万苦,Mark 终于找到了一位古代龙人.Mark 找到他时,他正在摆弄一些秘药,其中一些药丸由于是从很久以前流传下来的,发出了独特的光泽.古代龙人告诉了 Mark 一些他想知道的事情,看了看手中的秘药,决定考一考这位来访者. 古代龙人手中共有\(n\)粒秘药,我们可以用\(1\)表示「古老的秘药」,其余的用\(0\)表示.他将它们排成一列.古代龙人认为平衡是美的,于是他问 Mark 能选出多少个

2019.10.18模拟赛T3

题目大意: 求$\sum\limits_{i=1}^n\sum\limits_{j=1}^n[lcm(i,j)>n](n\leq 10^{10})$的值. 题解: 这题貌似有n多种做法... 为了更好统计,把原式变为$n^2-\sum\limits_{i=1}^n\sum\limits_{j=1}^n[lcm(i,j)\leq n]$. 然后开始毒瘤... 首先,考虑枚举$lcm(i,j)$,设为$d$,计算有多少对$i.j$的最小公倍数为$d$. 设$i=p_1^{a_1}p_2^{a_2}\

2019.10.26模拟赛

T1 序列 给定一长度为\(n\)的序列\(s\),定义其健美值为:\[\sum\limits_{i=1}^{n}|s_i - i|\]因为 zzq 喜欢健美,所以 zzq 希望减小\(s\)的健美值,以衬托 zzq 的健美.为了达到 zzq 的目的,zzq 希望你对序列进行旋转操作,一次旋转操作可以使序列中的所有元素前移一位,并使\(s_1\)移动到\(s_n\). 可以进行任意次旋转操作,zzq 希望旋转后的健美值最小,请找出这个最小值. SOV 智商检测题 我们发现对于每个数,移动每一次会

2019.10.22模拟赛

T1 合并集合 有\(n\)个集合,第\(i\)个集合记为\(S_i\),集合按环状排列,即第\(i + 1\)个集合右边是第\(i\)个集合,第\(n\)个集合右边是第\(i\)个集合. 一开始每个集合里只有一个数,每次你可以选择两个相邻的集合\(S,T\),然后合并成\(S \cup T\),之后你可以获得收益\(|S| \times |T|\),其中\(|S|\)表示集合\(S\)的元素个数. 你需要一直进行以上的操作直到只剩一个集合为止,求能获得的最大的收益之和. 断环为链,复制两倍区间

2019.10.31模拟赛

说在前面 考场遇见原题??? 上午刚做的 下午就\(T3\)考到了\(2333\) 然而还是因为忘了取模挂了28分 T1 Dove下跳棋 数据太水输出n-1可得90 Dove 喜爱下跳棋,在传统的跳棋基础之上,Dove 又延伸出了许多别的玩法.Dove 以一个一维数轴为棋盘下跳棋,总共会移动棋子?? ? 1 次.因为讨厌没有规律,所以Dove 每次只会恰好把棋子向右移动?? 个格子. Cicada 送给了Dove 一个长度为?? 的数列{??},为了表示感谢,Dove 打算以Cicada 送给他

10.2模拟赛总结

10.2 模拟赛总结 T1. 数位dp: 一个非常非常非常非常显然的数位 DP \([L,R] = [1,R]-[1,L-1]\) 所以是分别求两次小于等于某个数字的方案数 \(f(i,j,k)\) 表示从低位数起的第 \(i\) 位,按照规则计算后答案为 \(j\quad (j=0,1)\) \(k\) 表示只考虑后面结尾和 \(lmt\)后面几位 的大小关系 \((k=0,1)\) 考虑第 \(i+1\) 位,算一下新构成的数字并判断下大小就可以了 注意到 \(L,R\) 数据范围特别大,需

10.22 模拟赛

10.22 模拟赛 T1 染色 考虑每个连通块删成一棵树就好了. mmp场上就我路径压缩写炸.... #include<iostream> #define MAXN 200006 using namespace std; int n , m; int fa[MAXN] , siz[MAXN] , book[MAXN] , sz[MAXN]; int find(int x) { return x == fa[x] ? x : fa[x] = find(fa[x]); } int main() {

10.31 模拟赛

10.31 模拟赛 A LIS 考虑每个数字前从 $ m $ 降序构造到 $ a_i $ 即可. #include <iostream> #include<algorithm> #include<cstring> #include<cstdio> #include<vector> using namespace std; #define MAXN 300006 int n , m , k; int A[MAXN]; vector<int&g

2018/5/24模拟赛总结

shzr带病AK虐爆全场... T1n皇后: 这题没啥好说的... T2有重复元素的排列问题: [问题描述] 设R={ r1, r2 , -, rn}是要进行排列的n个元素.其中元素r1, r2 , -, rn可能相同.试设计一个算法,列出R的所有不同排列. [编程任务] 给定n 以及待排列的n 个元素.计算出这n 个元素的所有不同排列. [输入格式] 由perm.in输入数据.文件的第1 行是元素个数n,1≤n≤500.接下来的1 行是待排列的n个元素. [输出格式] 计算出的n个元素的所有不