海事大学C语言竞赛解题报告初赛.docx

上传人:b****8 文档编号:9424390 上传时间:2023-02-04 格式:DOCX 页数:16 大小:20.24KB
下载 相关 举报
海事大学C语言竞赛解题报告初赛.docx_第1页
第1页 / 共16页
海事大学C语言竞赛解题报告初赛.docx_第2页
第2页 / 共16页
海事大学C语言竞赛解题报告初赛.docx_第3页
第3页 / 共16页
海事大学C语言竞赛解题报告初赛.docx_第4页
第4页 / 共16页
海事大学C语言竞赛解题报告初赛.docx_第5页
第5页 / 共16页
点击查看更多>>
下载资源
资源描述

海事大学C语言竞赛解题报告初赛.docx

《海事大学C语言竞赛解题报告初赛.docx》由会员分享,可在线阅读,更多相关《海事大学C语言竞赛解题报告初赛.docx(16页珍藏版)》请在冰豆网上搜索。

海事大学C语言竞赛解题报告初赛.docx

海事大学C语言竞赛解题报告初赛

 

第五届微软编程大赛初赛解题报告

--ByPeterJC

 

01SkyAo的节操

题目描述Description

SkyAo决定做个程序来查看自己的节操变化量:

输入四个数字,如果是严格递增的数,那么输出JieCaoUp,严格递减的话,输出JieCaoDown,如果四个数字一样,那么输出JieCaoConstant,否则的话输出WhereisJieCao?

输入描述InputDescription

输入会是四个正整数,代表节操量读入。

每个整数会占一行。

样例输入SampleInput

30102020

输出描述OutPutDescription

JieCaoUp,JieCaoDown,JieCaoConstant,WhereisJieCao?

四种情况

样例输出SampleOutput

WhereisJieCao?

数据范围及提示DataSize&Hint

四个数字的范围为1..100

题目思路IdeaOfProblem

本题非常简单,定义四个变量,然后读入那四个整数,根据相应的条件给出相应的结果。

样例程序ExampleCode

#include

usingnamespacestd;

main()

{

inta[4],i;

boolb=1;

for(i=0;i<=3;i++)

cin>>a[i];

if(a[0]==a[1]&&a[0]==a[2]&&a[0]==a[3])

{

cout<<"JieCaoConstant";

return0;

}

for(i=1;i<=3;i++)

if(a[i]<=a[i-1])

b=0;

if(b)

{

cout<<"JieCaoUp";

return0;

}

b=1;

for(i=1;i<=3;i++)

if(a[i]>=a[i-1])

b=0;

if(b)

cout<<"JieCaoDown";

else

cout<<"WhereisJieCao?

";

}

02RP增加定理

题目描述Description

SkyAo最近心血来潮的参考GPA运算公式发明了一个RP增加均值定理:

RP增加均值=Σ(某事件增量*RP评级)/增量和

比如:

扶老奶奶过马路增量为2,遵守交通规则增量为1,热心帮助同学增量为3。

参考考试制度,满分为100,如果SkyAo做该事件的得分在69分以上,就算RP增加成功,会获得该事件所设定的增量。

举个例子而言,如果SkyAo帮助老奶奶过马路,但老奶奶其实不想过马路,虽然他扶老奶奶很认真,但还是只能算得了60分,那么就无法获得评级(评级为0),但该事件增量还是2,如果SkyAo得分90,那么就会得到2RP增量,并且评级为4。

换句话说,事件增量只与事件本身有关,与此人表现无关。

评级在0-4之间,最高评级为4,最低为0。

于是SkyAo决定写个程序来快速计算自己最近的RP增量。

输入描述InputDescription

请你从输入中读入相关数据。

输入的第一行包括一个整数n(1≤n≤10),表示他最近所做的好事。

接下来的n行每行两个实数a(0≤a≤8)和b(0≤b≤4),表示SkyAo的某事件增量和RP评级。

样例输入SampleInput

10

23.7

03

53.7

04

33.3

34

14

24

24

23.5

输出描述OutPutDescription

输出只包括一个实数,请保留2位小数。

样例输出SampleOutput

3.74

题目思路IdeaOfProblem

这题就是计算GPA。

GPA大家都会算吧,把学分都加起来,然后统计学分和绩点之积的和。

两个数的商便是本题的解。

当然别忘了保留两位小数。

样例程序ExampleCode

#include

#include

#include

#include

#include

usingnamespacestd;

intn;

doublea,b;

intmain()

{

cin>>n;

doublet1=0.0,t2=0.0;

for(inti=1;i<=n;i++)

{

cin>>a>>b;

t1=t1+a;

t2+=a*b;

}

printf("%.2lf\n",t2/t1);

return0;

}

 

03BobWu与网游

题目描述Description

很多童鞋喜欢玩一些lol、dota这类游戏,这类游戏有一个特点,在你不死的情况下连续杀人会有不同称号。

完成游戏后,BobWu非常后悔,他总是说“少死一次就好了”。

下面为连续杀人次数对应的称号

0/1/2-YouareaFoolishMan

3-YouareonaKillingSpree

4-YouareDominating

5-YouhaveaMega-Kill

6-YouareUnstoppable

7-YouareWickedSick

8-YouhaveaM-m-m-m....MonsterKill

9-YouareGodlike

10+-YouareBeyondGodlike(Somebodykillhim!

输入一组字符,其中只包含K和D,K代表杀敌,D代表死亡,求他少死一次的情况下的最高称号。

输入描述InputDescription

输入一组字符,其中只包含K和D

输出描述OutputDescription

他少死一次的情况下的最高称号。

样例输入SampleInput

KKKDKKDDDKKKK

样例输出SampleOutput

YouhaveaMega-Kill

数据范围及提示DataSize&Hint

字符串长度小于20000

题目思路IdeaOfProblem

此题的关键在于求少死一次的最大击杀数。

我们可以将D作为分割符,将连续的K的个数记录在数组中,然后求出数组中相邻两位之和的最大值即可。

最后将对应的称呼进行输出。

样例程序ExampleCode

#include"stdio.h"

intmain()

{

chars[32767];

inti,j=0,ss=0,t[1000];

scanf("%s",s);

for(i=0;s[i]!

='\0';i++)

if(s[i]=='D')

{

t[j++]=ss;

ss=0;

}

else

ss++;

t[j++]=ss;

ss=0;

if(j==0)

ss=t[0];

else

for(i=0;i

ss=(t[i]+t[i+1])>ss?

(t[i]+t[i+1]):

ss;

switch(ss){

case0:

printf("YouareaFoolishMan");break;

case1:

printf("YouareaFoolishMan");break;

case2:

printf("YouareaFoolishMan");break;

case3:

printf("YouareonaKillingSpree");break;

case4:

printf("YouareDominating");break;

case5:

printf("YouhaveaMega-Kill");break;

case6:

printf("YouareUnstoppable");break;

case7:

printf("YouareWickedSick");break;

case8:

printf("YouhaveaM-m-m-m....MonsterKill");break;

case9:

printf("YouareGodlike");break;

default:

printf("YouareBeyondGodlike(Somebodykillhim!

)");

}

return0;

}

 

04Linkinpaoger的节操竞赛

题目描述Description

Linkinpaoger平时总喜欢刁难你,这次刁难完之后发现自己的节操全无,于是准备向上帝求助,希望能获得一些新节操,上帝告诉Linkinpaoger:

与你比赛一场,规则如下:

在一个房间里放置了若干堆节操,每次只能从某一堆中取走部分或者全部的节操(由你先取第一份),取到最后一份节操的人获胜。

在比赛前允许大家进入房间看看节操们。

如果Linkinpaoger赢了,就能免费获得房间里所有的节操。

于是Linkinpaoger来邀请你参加比赛,你不想浪费无意义的时间,所以去房间看了节操堆数和各堆的数目,据说,这样就能确定在最优情况下谁会赢。

那么……有了堆数和各堆数目,谁才会赢呢。

输入描述InputDescription

第一个值N为节操堆数,接下来输入N个数,每个数表示各堆节操数目n,N与n均为正整数

输出描述OutputDescription

赢得这次比赛的人:

Linkinpaoger或Me

样例输入SampleInput

211

样例输出SampleOutput

Linkinpaoger

数据范围及提示DataSize&Hint

题目思路IdeaOfProblem

如果仅仅是两堆石子,那么上述两个问题很好解决:

1〉当两堆石子数目相等的时候,当前局面为必败局面,否则为必胜局面,显然,两堆均为0颗是满足这个方法的;

2〉如果当前局面是必胜局面,那么从石子较多的那一堆里面取,使得两堆石子数相等,这样便转化到了必败局面。

然而,对多于两堆石子,1〉可以照旧,但是这样一来2〉远远没有这么简单,因为不太可能取后使得所有堆数目都一样(除非除了石子最多的一堆之外其它所有堆石子数目都相等)。

因此需要找一组更加有效的方法,想到的方法是这样的:

1〉把所有堆的石子数目用二进制数表示出来,当全部这些数按位异或结果为0时当前局面为必败局面,否则为必胜局面;

2〉(定理0)一组自然数中必然存在一个数,它大于等于其它所有数按位异或的结果。

因此在必胜局面下,因为所有数按位异或的结果是大于零的,那么通过一次取,将这个(大于其它所有数按位异或的结果的)数下降到其它所有数按位异或的结果,这时局面就变为必败局面了。

有了上述理论,此题就很简单了。

样例程序ExampleCode

#include"stdio.h"

longtemp[100];//房间的个数

intmain()

{

inti,n;

longmin;

scanf("%d",&n);

for(i=0;i

scanf("%ld",&temp[i]);//第i个房间的节操数量

min=temp[0];

for(i=1;i

min=min^temp[i];//按位异或

if(min==0)

printf("Linkinpaoger");//我输

else

printf("Me");//我赢

//printf("%ld",min);

return0;

}

 

05数学魔王

题目描述Description

Linkinpaoger做了个梦,梦中Anonymous被魔王拐走了,而他过五关斩六将的来到魔王的城堡,魔王告诉他,

他的城堡的城门需要用三个素数才能打开,魔王会给出一个大于5的整数,这三个素数的和是这个整数,

Linkinpaoger想到,可以用计算机来排列出所有可能的情况,Linkinpaoger想知道所有可能的情况。

输入描述InputDescription

一共一行,为一个大于5的正整数N

输出描述OutPutDescription

输出符合条件的前2000个素数组合,输出排列按如下顺序:

先比较第一个数的大小,第一个数小的先输出,如果相同,比较第二个数,第二个数小的先输出,最后比较最后一位。

样例输入SampleInput

10

样例输出SampleOutput

235

253

325

352

523

532

数据范围及提示DataSize&Hint

1<=N<=30000

因为要打印的内容较多,建议大家使用printf函数来输出,这样可以节省一些时间。

题目思路IdeaOfProblem

这题第一个问题便是怎么快速的生成素数?

这里我们推荐大家使用筛数法。

从2循环N,如果他不能被我们已经找到的素数整除的话,那么就可以认为它也是一个素数。

这样我们便可以以O(x)的复杂度解决这个问题,而且生成的素数序列是升序的。

(x为1..N的素数个数)

第一个问题解决后,那么下一个问题自然便自然的呈现在我们面前。

如何找出在上面生成的素数数列中找出和为定值N的三个素数?

这里其实有两种方法,一种是深度优先搜索加一定的剪枝,另外一种是把他看成背包问题。

这里我们受时间所限,就以深度优先搜索为例。

深度优先搜索本身的复杂度是O(2^N),对于这道题明显是不合适的,所以我们需要剪枝。

首先如果我们枚举的三个数的和已经大于那个定值,那么将搜索进行下去是没有意义的。

其次,要是前面两个数已经确定的情况下,如果已经找到第三个数的话,那么搜索也没有必要进行下去。

如果我们就用以上的思路去写程序,经过测试后一定会发现,较大的奇数可以通过时限,然而较大的偶数却不行。

这是因为奇数的情况数较少,只有奇数+奇数+奇数和奇数+偶数+偶数这两种情况。

前面那种情况很少出现,而后面那种情况只有一个解。

而偶数则不同,

有偶数+偶数+偶数,偶数+奇数+奇数两种情况,前面那种只能是2+2+2=6,后面是2+奇数+奇数。

奇数素数+奇数素数的情况相较之前的情况要多的多。

不过,值得庆幸的是,2必定是这三个素数中的一个。

这样我们便能降低深度优先搜索的深度,用标记法降低时间复杂度。

样例程序ExampleCode

#include

#include

#include

#definemaxn30005

boolvis[maxn];

intprime[maxn];

intnum,s,c;

boolselected[maxn]={0};

boolonce;

usingnamespacestd;

intClear()

{

memset(vis,0,maxn);

intnum=0;

vis[1]=1;

for(longi=2;i

{

if(!

vis[i])

{

prime[++num]=i;

}

for(intj=1;j<=num&&i*prime[j]

{

vis[prime[j]*i]=1;

if(i%prime[j]==0)

break;

}

}

returnnum;

}

booldfs_even(intdepth,intsum,int*nums)

{

if(depth==3)

{

if(sum==s)

{

selected[nums[0]]=true;

selected[nums[1]]=true;

selected[nums[2]]=true;

printf("%d%d%d\n",nums[0],nums[1],nums[2]);

c++;

returntrue;

}

else

{

returnfalse;

}

}

else

{

intnowsum=sum;

for(inti=1;i<=num;i++)

{

nowsum=sum+prime[i];

if(nowsum>s||c==2000)

{

break;

}

elseif((once&&selected[prime[i]]==false))

{

continue;

}

else

{

nums[depth]=prime[i];

if(dfs_even(depth+1,nowsum,nums))

break;

if(depth==0)

{

once=true;

}

}

}

}

returnfalse;

}

booldfs_odd(intdepth,intsum,int*nums)

{

if(depth==3)

{

if(sum==s)

{

printf("%d%d%d\n",nums[0],nums[1],nums[2]);

c++;

returntrue;

}

else

{

returnfalse;

}

}

else

{

intnowsum=sum;

for(inti=1;i<=num;i++)

{

nowsum=sum+prime[i];

if(nowsum>s||c==2000)

{

break;

}

else

{

nums[depth]=prime[i];

if(dfs_odd(depth+1,nowsum,nums))

{

break;

}

}

}

returnfalse;

}

}

intmain()

{

cin>>s;

num=Clear();

intss[3]={0};

c=0;

if(s%2!

=0)

dfs_odd(0,0,ss);

else

{

once=false;

dfs_even(0,0,ss);

}

return0;

}

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 工作范文 > 其它

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1