海事大学C语言竞赛解题报告初赛.docx
- 文档编号:9424390
- 上传时间:2023-02-04
- 格式:DOCX
- 页数:16
- 大小:20.24KB
海事大学C语言竞赛解题报告初赛.docx
《海事大学C语言竞赛解题报告初赛.docx》由会员分享,可在线阅读,更多相关《海事大学C语言竞赛解题报告初赛.docx(16页珍藏版)》请在冰豆网上搜索。
海事大学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; }
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 海事 大学 语言 竞赛 解题 报告 初赛