洛谷ZHC邀请赛---2018年元旦马拉松欢乐赛之《我的一位程序员朋友》

emmmmmmmm
现在的时间是北京时间2018年1月2日凌晨2:09
一小时前我开始做这套题(T1在学校水过了)

T1:开心农场

传送门:https://www.luogu.org/problemnew/show/U17645
题目描述:

小明最近又迷上了一款《开心农场》的游戏,他打算在农场里种一排花,总共有红色、蓝色、紫色三种种类的花供选择,他希望红色和红色的花不要相邻,蓝色和蓝色的花不要相邻。

当一排有两块地时,可以种花的方案共有:红蓝,红紫,蓝红,蓝紫,紫红,紫蓝,紫紫共7种方案。

作为小明的好朋友,请你编写一个程序,帮小明求出种花的方案数量。

输入输出格式

输入格式:
第一行包括一个整数n,表示一排有n块地。

输出格式:
输出仅一行,输出种花的方案数量。

输入输出样例

输入样例#1:
2
输出样例#1:
7
说明

对于30%的数据,1<=n<=10

对于50%的数据,1<=n<=20

对于100%的数据,1<=n<=40

.
.
.

题解:这题其实是一眼题来的…………..。但是,我相信还是会有人去打暴力试图水过。不废话,直接讲正解。
.
.
.

先创一个数组f,f[i]表示有i块地时的方案数
这里写图片描述
那么f[i]和f[i-1]d的关系如图所示(本人字丑,望见谅)
(1)f[i]的最后一块为红色时方案数为f[i-1]的最后一块放蓝或紫的方案数。
(2)f[i]的最后一块为蓝色时方案数为f[i-1]的最后一块放红或紫的方案数。
(3)f[i]的最后一块为紫色时方案数为f[i-1](无论放什么色都行)方案数。
然后我们把它们都加在一起,便是f[i]=f[i-1]的方案数*2+f[i-1]最后一块放紫色的方案数,而这f[i-1]最后一块放紫色的方案数又恰好是f[i-2]的方案数(类比一下f[i]最后一块放紫色与f[i-]方案数的关系)

所以我们得到了一个至关重要的式子
这里写图片描述

还有,这题有个坑,当n=40时,答案是2470433131948081,不用long long 绝对要炸的。

上代码:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
long long  n,m,f[100000];
int main()
{
    cin>>n;
    f[0]=1;f[1]=3;
    for(int i=2;i<=n;i++)
    {
        f[i]=f[i-1]*2+f[i-2];
    }
    cout<<f[n];
    return 0;
}

.
.
.
.
.
.
.

T2:摩尔斯电码

传送门;https://www.luogu.org/problemnew/show/U17647
题目描述:

计算机专业的小明,为了体现自己的专业和神秘感,他打算写一封由摩尔斯电码编码的情书送给心仪的女生,由于他整日玩游戏,专业上的学习一落千丈,自己写不出程序。作为他的好朋友,他请你帮他写一个将英文翻译成摩尔斯电码的程序,以便于以后经常使用。

摩尔斯电码(又译为摩斯电码,Morse code)是一种时通时断的信号代码,这种信号代码通过不同的排列顺序来表达不同的英文字母、数字和标点符号等。编码主要是由两个字符表示:”.”、”-“,一长一短。电影《风声》中就是采用在衣服上缝出摩尔密码,将消息传播出去。动漫《名侦探柯南》中《推理对决,新一vs冲矢昴》也是用了这种方法。

摩尔斯电码英文字母对照表如下:
这里写图片描述

字母A的摩尔斯电码为:.-

字母B的摩尔斯电码为:-…

输入输出格式

输入格式:
一行长度为N(N<=10000)英文句子,英文字母全部为大写且字母之间没有空格,没有其它的特殊字符。

输出格式:
对应英文句子的摩尔电码。各个字母之间的摩尔斯电码用单个空格隔开。

输入输出样例

输入样例#1:
DH
输出样例#1:
-.. ….
输入样例#2:
ILOVEDH
输出样例#2:
.. .-.. — …- . -.. ….
说明

对于30%的数据,1<=N<=100

对于50%的数据,1<=N<=1000

对于100%的数据,1<=N<=10000

解析:这种题我还能说什么???
输入一个字符串数组,依次判断输出就好……….
不过你每个字母对应的摩尔斯电码千万别打错……………

.
.
.
.
还有,我最后一个字母后面没有输出一个空格,我也不知道潮哥的数据卡不卡这个,反正我因为这个被dhoj坑惨过。。。。。

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
char a[1000000];
long long int n,m;
void out(int i)
{
    switch(a[i])
    {
        case 'A':cout<<".-";return;
        case 'B':cout<<"-...";return;
        case 'C':cout<<"-.-.";return;
        case 'D':cout<<"-..";return;
        case 'E':cout<<".";return;
        case 'F':cout<<"..-.";return;
        case 'G':cout<<"--.";return;
        case 'H':cout<<"....";return;
        case 'I':cout<<"..";return;
        case 'J':cout<<".---";return;
        case 'K':cout<<"-.-";return;
        case 'L':cout<<".-..";return;
        case 'M':cout<<"--";return;
        case 'N':cout<<"-.";return;
        case 'O':cout<<"---";return;
        case 'P':cout<<".--.";return;
        case 'Q':cout<<"--.-";return;
        case 'R':cout<<".-.";return;
        case 'S':cout<<"...";return;
        case 'T':cout<<"-";return;
        case 'U':cout<<"..-";return;
        case 'V':cout<<"...-";return;
        case 'W':cout<<".--";return;
        case 'X':cout<<"-..-";return;
        case 'Y':cout<<"-.--";return;
        case 'Z':cout<<"--..";return;
    }
}
int main()
{
    scanf("%s",&a);
    n=strlen(a);
    for(int i=1;i<n;i++)
    {
        out(i-1);
        cout<<" ";
    }
    out(n-1);
    return 0;
}

.
.
.
.
.
.

T3:物资分组

传送门:https://www.luogu.org/problemnew/show/U17682

题目描述

元旦快到了,荒野行动游戏策划组为了让玩家假期中玩的更开心,想给游戏中的城镇添置一些元旦色彩系列的物资以供玩家获取使用,每个物资都有其相应的使用价值,为使得游戏中各个城市所添置的物资价值相对均衡,需要把每个物资根据价值进行分组,但每个城镇最多只能添置两件物资,所以每组物质最多只能包括两件, 并且每组物资的价值之和不能超过一个给定的整数。为了保证在尽量短的时间内完成所有物资的分组任务,使得分组的组数最少,策划组发布悬赏任务,谁能够设计出计算机程序快速帮他们完成分组任务就可以获得一笔赏金,小明渴望得到赏金,他找到了编程大神的你,要你写一个程序,找出所有分组方案中分组数最少的一种,输出最少的分组数目,他如果获得赏金,会分一半给你。

输入输出格式

输入格式:
第1行包括一个整数w,为每组物资价值之和的上限。 第2行为一个整数n,表示所有物资的总件数G

第3-n+2行每行包含一个正整数Pi (5 <= Pi <= w3)w表示所对应物资的价值。

输出格式:
输出仅1行,包含一个整数 e,最少的分组数

输入输出样例

输入样例#1: 复制
100
9
90
20
20
30
50
60
70
80
90
输出样例#1: 复制
6
说明

50%的数据满足: 1 <=n <= 15

100%的数据满足: 1 <= n <= 30000, 80 <= W <= 200
.
.解析:
这题要我们求的是最少的分组数,那我们想一下怎么样它的分组数才会最少呢?
对,就是在尽可能把可以配对的物资陪在一起的情况下产生最小组数。
那怎么样去尽可能地把它们凑到一起呢??
显然,把较小的和较大的先配到一起会最好。
那么我们只需要把记录物资价值的数组排个序,然后从数组两头开始配对即可。
.
.
.
.
上代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
long long l,r,n,value[1000000],w,ans=0;
int main()
{
    cin>>w>>n;
    for(int i=1;i<=n;i++)
    {
        scanf("%lld",&value[i]);
    }
    sort(value+1,value+n+1);
    l=1;r=n;
    while(l<=r)
    {
        if(value[l]+value[r]<=w)ans++,l++,r--;
        else 
        {
            ans++;
            r--;
        }
    }
    cout<<ans;
    return 0;
}

.
.
.
.
.
.

T4:乌龟问题

传送门:https://www.luogu.org/problemnew/show/U17683

题目描述

为了响应国家大学生自主创业的号召,小明打算在宿舍里养乌龟发家致富,他从非洲进口了一对神奇的乌龟,一对乌龟每个月可以生一对小乌龟,而一对乌龟从出生后第3个月起每月生一对小乌龟,乌龟很长寿,没有死亡的情况。作为和他一起创业的股东,你决定编写一个程序来计算第n个月会有多少对乌龟?

输入输出格式

输入格式:
第1行包括一个整数n(1<=n<=200)

输出格式:
输出仅一 行,包含一个整数,输出n个月有多少对乌龟。

输入输出样例

输入样例#1:
2
输出样例#1:
1
输入样例#2:
3
输出样例#2:
2
说明

50%的数据满足: 1 <=n <= 80

100%的数据满足: 1<= n <= 200

.
.
.
.
.
解析:题目大概就是说有一对乌龟,一个月可以繁殖一对,一对乌龟在其出生后第三个月开始就也可进行繁殖,问个月份后的乌龟对数。
很自然的会想到递推推下去,
a1:当前这一个月处于处于出生后第一个月的乌龟对数
a2:当前这一个月处于处于出生后第一个月的乌龟对数
can:当前可以繁殖下一代的乌龟对数
month:当前是第几个月

上一个月原来处于出生后第一个月的乌龟在这个月就是处于第二个月啦,上个月刚出生的这个月就是处于出生后第一个月啦,上个月处于出生后第二个月的这个月就可以繁殖啦!!!
就这样推下去,知道递归到第n个月为止,便有答案。
.
.
.
.

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
long long  n;
long long  a,c,a1,a2,can,month;
int main()
{
    cin>>n;a2=0;a1=1;can=0;
    for(long long  i=2;i<=n;i++)
    {
        can+=a2;
        a2=a1;
        a1=can;
    }
    cout<<a1+a2+can;
    return 0;
}

其实这样只有50分
加上高精度才会AC嘛,但我不想打了,毕竟北京时间凌晨2:00+。

.
.
.
.
.
.

T5:.亚瑟王

传送门:https://www.luogu.org/problemnew/show/U17684

题目描述

计算机专业的小明非常喜欢玩王者荣耀手游,这次他选择骑士亚瑟王打上单,但是上单敌人太强,他决定猥琐发育,待在塔下领取金币。游戏第一秒,亚瑟王获得1枚金币;之后二秒(第二秒和第三秒),每秒收到2枚金币;之后三秒(第四、五、六秒),每秒收到3枚金币;之后四秒(第七、八、九、十秒),每秒收到4枚金币……

这种领取游戏金币的情况会一直这样延续下去,直到游戏结束,当连续 N 秒每秒收到 N 枚金币后,亚瑟王会在之后的连续 N+1 秒里,每秒收到 N+1 枚金币,预计这局游戏会在k秒结束,请计算在前 K 秒里,亚瑟王一共获得了多少金币。

输入输出格式

输入格式:
输入只有 1 行,包含一个正整数 K,表示领取金币的秒数。

输出格式:
输出只有 1 行,包含一个正整数,即亚瑟王收到的金币数。

输入输出样例

输入样例#1: 复制
1000
输出样例#1: 复制
29820
说明

对于 100%的数据,1 ≤ K ≤ 10,000。

.
.
解析:
这题一看就是可以一个for循环模拟暴力的嘛……………….
但是,我们也可稍微追求优雅那么一丝丝的暴力的嘛……………
.
大概思路就是,用一个变量c记录从现在的第i+1秒到未来的第i+c秒可收获的金币数。
c每次都加上一,然后判断一下第i+c秒是否小于k秒。
如果小于,那么ans(答案)就加上c*c(在连续c秒里都收获了c个金币嘛)。
如果大于或等于的话,就把ans加上(n-i)*c再输出就好。
.
.
.
.

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
long long k,n,ans=0,i=0,c=1;
int main()
{
    cin>>k;
    while(i<=k)
    {
        if(i+c<k)
        {
            i+=c;
            ans+=(c*c);
            c++;
        }
        else 
        {
            ans+=(k-i)*c;
            printf("%lld",ans);
            return 0;
        }
    }
}

.
.
.
.
写到这里,时间是凌晨3:36………..
我选择
去爬数学青云梯…………….

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值