牛客寒假算法基础集训营3(部分)

传送门:点我

C题:处女座点名

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld

题目描述



处女座觉得自己手上的经费可能不太够,于是决定给牛逼学生们带家教。

一天他去上课用自己的火眼金睛感觉教室里有一个学生没有来,于是他就叫学生们报出自己的学号。

已知这个班上的学号是从1开始连续编号的,处女座告诉你这个班上有多少人,想问问你到底是谁没有来。

输入描述:

输入数据共两行,第一行为一个整数N,表示班上的学生数量。

第二行为一行N-1个整数,表示已经来的学生的学号,按升序给出。

输出描述:

输出一个整数,为没有来的学生的学号。
示例1

输入

3
1 3

输出

2

备注:

2N200,000


按题意做就行
代码:
#include<bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define MM(x) memset(x,0,sizeof(x))
#define MMINF(x) memset(x,INF,sizeof(x))
typedef long long LL;
int main()
{
    int n;scanf("%d",&n);
    int ans = n;
    for(int i = 1 ; i <= n-1 ; i++){
        int x;
        scanf("%d",&x);
        if(x != i &&ans==n){
            ans = i;
        }
    }
    printf("%d\n",ans);
}
/*
3
1 3
*/

D题:处女座的训练

题目描述

处女座靠着自己的家教本领赚够了去比赛的钱,于是开启了疯狂训练。在每个夜深人静第二天不收作业的夜晚,他都会开始刷题。

"今日又是一个刷题的夜晚。"他挑选了n道题开始刷,而题太多,刷不掉,理还乱(呜呜)、自己没有解决的题目每分钟都会给他带来 bibi的疲倦值,而解决每一道题目都需要花费aiai分钟的时间。

当然,处女座一般都是考虑清楚了再写题的,所以他在写题的时候都会精神抖擞,也就是说,当前正在写的那一题并不会给他带来任何疲劳。

为了迎接后天要收的作业和明天要遇到的小姐姐,他想让今晚的刷题尽可能的轻松,那请你帮他找出最小所需要的疲倦值吧。

输入描述:

输入数据共包括n+1行,第一行包括一个n表示处女座今晚打算训练的题的数量。

接下来n行,每行包括两个整数ai,biai,bi,分别表示处女座刷掉本题要花费的时间和本题每分钟会带来的疲倦值。

输出描述:

一行包括一个整数,表示处女座今晚训练会产生的最小疲倦值。
示例1

输入

6
6 1
4 5
4 3
6 2
8 1
2 6

输出

86

说明

先做第6个题,增加(1+5+3+2+1)*2= 24 点疲倦值,再做第2个题,增加28点疲倦值,随后依次是第3,4,1,5道题,增加16,12,6点疲倦值。总共的疲倦值是24 + 28 + 16 + 12 + 6 = 86点。

备注:

2N1052≤N≤105.
2ai41062≤ai≤4⋅106.
1bi1000



贪心,策略是按 每个作业的分钟疲劳值 排序,具体见代码。
#include<bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define MM(x) memset(x,0,sizeof(x))
#define MMINF(x) memset(x,INF,sizeof(x))
typedef long long LL;
struct node{
    LL a,b;
    double d; 
}p[100001];
bool cmp(node x,node y){
    return x.d > y.d;
}
int main()
{
    int n;scanf("%d",&n);
    LL sum = 0;
    LL ans = 0;
    for(int i = 0 ; i < n ; i++){
        scanf("%lld %lld",&p[i].a,&p[i].b);
        sum += p[i].b*1LL;
    }
    for(int i = 0 ; i < n ; i++){
        p[i].d = (p[i].b*1.0)/p[i].a; 
    }
    sort(p,p+n,cmp);
    for(int i = 0 ; i < n ; i ++){
        sum -= p[i].b*1LL;
        ans += sum*p[i].a*1LL;
    }
    cout<<ans*1LL<<endl;
}

E题:处女座和小姐姐

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld

题目描述

既然昨天晚上处女座已经训练了,明天才要交作业,那今天就是平淡无奇要上课的一天了。

然而处女座也想自己的小姐姐了,可是这节课是老师安排座位,处女座坐在(1,1),而小姐姐坐在(n,m)。他们之间只能通过传纸条的方式来交流感情。对于处女座而言,他上课不想过度分心,因此并不想传纸条,只在那里趁机折千纸鹤。

老师上课喜欢用"开火车"的方式让大家轮流回答问题,显然处女座作为(1,1)位,会被第一个叫起来回答,之后老师将依次叫起 (2,1),(3,1),.(n,1),(n,2),(n1,2)(1,2),(2,1),(3,1),….(n,1),(n,2),(n−1,2)⋯(1,2),⋯的人起来回答问题,每个人回答问题需要1秒。处女座在自己回答完以后会以每秒1个千纸鹤的速度折叠,在小姐姐开始回答问题的时候停止折叠。

处女座想知道,他这节课一共要折多少个千纸鹤?

输入描述:

输入文件包含T+1行,第一行包含一个整数T,表示用例组数。

接下来T行,每行包含两个整数n,m表示小姐姐的位置和教室的大小。

输出描述:

对于每一组用例,用一行输出一个整数,表示处女座要折的千纸鹤的个数。
示例1

输入

1
3 3

输出

7

备注:

2n,m1,000

根据题目直接算即可,注意奇数行和偶数行最后的拐点问题,即需要把小姐姐的位置分奇偶数考虑。
代码:
#include<bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define MM(x) memset(x,0,sizeof(x))
#define MMINF(x) memset(x,INF,sizeof(x))
typedef long long LL;
int main()
{
    int _;
    for(scanf("%d",&_);_--;){
        LL n,m;
        cin>>n>>m;
        if(m&1)
            cout<<(n*m*1LL-2LL)<<endl;
        else
            cout<<(n*(m-1)*1LL-1LL)<<endl;
    }
}/*
1
3 3
*/
 
  

G题:处女座和小姐姐(三)

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
 
  

题目描述

 
  
经过了选号和漫长的等待,处女座终于拿到了给小姐姐定制的手环,小姐姐看到以后直呼666!

处女座其实也挺喜欢6这个数字的,实际上他做手环的时候选取的k=6。所以他对于包含数码6的数字极其敏感。每次看到像4567这样的数字的时候他的心就像触电了一样,想起了小姐姐。

现在你要给处女座展示一系列数字,你想知道他的内心会激动多少次。对于同一个数字,他最多只会激动一次,即如果这个数是66666,他还是只会激动一次。

输入描述:

一行包括两个数字l,r,表示你给处女座展示的数字范围为[l,r]。

输出描述:

一行一个整数,表示处女座内心激动的次数。
示例1

输入

10 20

输出

1

备注:

0lr1018

思路:看到选取某个满足条件的数,和那么大的区间,直接考虑数位DP。dp[i][j]表示,dp[i][j]表示i+1位数,且以j为开头,不包含6的数的个数。
递推式则很显然能得到:dp[i][j] = dp[i][j] + (j == 6? 0: dp[i-1][k]); 即当当前位是6时,不递推上去,其他数字则递推到下一个状态。
不大会的可以先做“不要62”这道题。另外注意范围是long long。

代码:
#include<bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define MM(x) memset(x,0,sizeof(x))
#define MMINF(x) memset(x,INF,sizeof(x))
typedef long long LL;
const int maxn = 20;
LL dp[maxn][maxn];//dp[i][j]表示i+1位数,且以j为开头,不包含6的数的个数
void init(){
    memset(dp,0,sizeof(dp));
    dp[0][0] = 1LL;
    for(int i = 1 ; i <= 19 ; i ++){
        for(int j = 0 ; j < 10 ;j ++){
            for(int k = 0 ; k < 10 ; k ++){
                if(j != 6){
                    dp[i][j] += dp[i-1][k]*1LL;
                }
            }
        }
    }
}
LL solve(LL x){
    int digit[20];
    int k = 0;
    LL tmp = x;
    while(tmp){
        digit[++k] = tmp%10;
        tmp/=10;
    }
    digit[k+1] = 0;
    LL ans = 0;
    for(int i = k;i > 0; i--){
        for(int j = 0 ; j < digit[i] ; ++j){
            if(j != 6){
                ans += dp[i][j]*1LL;
            }
        }
        if(digit[i] == 6) break;
    }
    return x - ans;  
}
int main()
{
    init();
    LL a,b;
    while(cin>>a>>b) 
    cout<<(solve(b+1LL) - solve(a))*1LL<<endl;
}
/*
0 1000000000000000000
*/
 
   
   
  

 I题:处女座的约会

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld

题目描述

 
处女座放完了"高利贷",拿到了不少的资金,又可以和小姐姐约会啦!(之前不还是攒钱打比赛的吗)现在处女座拿到了一份宁波市旅游地图决定和小姐姐一起去玩耍。他们来到了动物园,去参观里面的动物。但是很不幸的是,他们在游玩的途中遇到了一只恶龙。

恶龙长有n个头,但经过了处女座的调教,恶龙变得善良了一些。它的n个头每个头要么仍是邪恶的头,用“1”表示,要么已经变得善良,用“0”表示,因而恶龙的n个头就可以用n位01串来表示。而此时处女座要发挥自己的勇士形象,要把所有的龙头都变成 0000000000⋯00完全善良的龙头。每一次,他可以砍掉龙最右侧的一个头,同时龙会在最左侧长出新的一个头,以保证龙头数量不变。如果他砍掉的是一个1,即邪恶的头,他可以决定龙在最左侧会长出什么样的头;但如果他砍掉了一个善良的头,那么玻璃心的恶龙将会在左侧不受控制的长出一个随机的头,既可能是善良的头,也可能是邪恶的头,而且它总会与处女座作对,尽力的破坏他的计划。

现在给你一个恶龙头的初始状态,即一个01串,请帮助处女座判断一下,能否在有限步之内让全部的龙头都变成善良的龙头。

输入描述:

输入第一行T,表示用例组数。

之后T行,每行一个01串S表示龙头的初始状态,“0”表示善良的头,“1”表示邪恶的头。

输出描述:

对于每组数据,处女座能否将全部的龙头变成善良的头,可以的话输出“cnznb”,不可以则输出“ljcnz”(不含引号)。
示例1

输入

1
1111

输出

cnznb

备注:

T1000T≤1000
|S|100|S|≤100
注意,这个问题可能没有你想的那么简单。显然,处女座必须把一些1变成0,这样才能让1的数量减少并消失。但是如果只是简单的每次把1变成0,最终不见得能取胜。比如,如果龙头的状态是101,那么去掉最右边的1并选择在左边长出一个0,则龙头会变成010;再把010右边的0去掉后,如果左边仍长出一个1,则龙头又变回了101的状态,如此反复,将永远不能得到000。


思路:
看到题目之后以为要用sg函数。手推了一下发现有个规律:如果是全1肯定可以变成全0(因为1可以自己选择变成0或者1,不需要随机);
那么很自然的过渡到几种情况:
①:最右边是1,此时砍掉之后我们可以最左边增加一个1
②:最右边是0,此时砍掉后最左边随机加0或者1,假设是1,情况则同①
③:最右边是0,此时砍掉后最左边随机加0或者1,假设是0,那么先不管,等到下次再回来的时候进入随机。

发现只要是,恶龙砍掉后加的头还是恶龙,则可以把1的比例不断增加,直到全1。
此时则可全部变成0。
到此,发现无论输入的是什么,都能在有限步变成全0.(题目的提示很有误导性,当然也会带来启发,例如句子“
但是如果只是简单的每次把1变成0,最终不见得能取胜”)暗示可以变1。
代码:
#include<bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define MM(x) memset(x,0,sizeof(x))
#define MMINF(x) memset(x,INF,sizeof(x))
typedef long long LL;
int main()
{
    int n;
    scanf("%d",&n);
    while(n--){
        string s;
        cin>>s;
        cout<<"cnznb"<<endl;
    }
}
 
   
  
 

猜你喜欢

转载自www.cnblogs.com/Esquecer/p/10324811.html