您的位置:首页 > 编程语言

现场编程比赛普及组决赛题解

2015-11-28 21:10 330 查看
问题 A: 最小钱

时间限制: 1 Sec 内存限制: 128 MB

提交: 107 解决: 16

[提交][状态][讨论版]

题目描述

厂源想要给喜欢的女生买礼物,但是没钱。怎么办呢?只好去街头玩悠悠球卖艺了。可是奇怪的是,卖艺了一天,得到的钱只有一毛,两毛和五毛钱。可怜的厂源看着这些钱,突然想把同一面值的钱放在一起,然后计算这些钱不可以组成的最小面值是多少。

输入

有多组输入,每一组输入包括三个数num_1,num_2,num_3分别代表一毛、两毛、五毛钱的数量,输入三个0,0,0表示输入结束。保证输入都在整形范围内。

输出

每组输入数据,每行输出一个数s,表示厂源得到的钱中,所不能组成的最小币值。

样例输入

1 1 3

0 0 0

样例输出

4

#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<string.h>
#include<time.h>

int n1[8005],n2[8005];
int num[4],p[4],sum;

void generating_function(  )
{
memset(n1,0,sizeof(n1));
memset(n2,0,sizeof(n2));
n1[0]=1;
/* 初始化 ,这里 n1[0]=1 直接意义是总财富为零的组合方式是被接受的
即一个硬币都不放,尽管可能在某些题中不满足题意,但这个赋值是必要的
只有这样,后面的j=0时的判定才有意义,由于母函数主要是通过加法来
实现组合的存在性,在每次展开刚开始时,必定要求单纯的本身是存在的
n1[5]=1 ,代表 财富为5是可能的组合,现在当有一枚10元的硬币,那么
n1[15]=1,因为n1[5]=1 成立,15=10+5,所以后式,现在考虑刚开始处理
一枚 5 元的硬币,假设之前n1[5]=0, 那么如何使得 n1[5]=1成立呢 ,
显然 5=5+0; 所以n1[0]=1是有意义的。
*/
for(int i=1;i<=3;++i)  // i从 1 开始很容易理解,因为我舍弃了num[0].
{
for(int j=0;j<=sum;++j)
// j从 1 开始呢,上面已经说明了原因 。
for(int k=0;k<=num[i]&&k*p[i]+j<=sum;++k)
// 我考虑过 k为什么从0开始,本来是这样想,
// 这种判定是否存在的题目可以直接从1开始,
// 我认为,如果取 k=0,那么 n2[k*p[i]+j]==n2[j]
// 后面又赋值给 n1[j] 不是多此一举吗,其实不是这样的
// 这个时候又要考虑到n1[0]这个特殊的例子了,如果k从1开始
// 那么一次n1与n2 之间的赋值后,则出现 n1[0]=0,着显然不行
if(n1[j])
n2[k*p[i]+j]=1;
for(int j=0;j<=sum;++j)
{
n1[j]=n2[j];
n2[j]=0;
}
}
}

int main()
{
p[1]=1,p[2]=2,p[3]=5;
while(scanf("%d%d%d",&num[1],&num[2],&num[3]),num[1]|num[2]|num[3])
{
sum=num[1]+2*num[2]+5*num[3];
generating_function(  );
for(int i=0;i<=sum+1;++i) // 不是sum,而是sum+1.
if(n1[i]==0)
{
printf("%d\n",i);
break;
}
}
return 0;
}


问题 B: 求余数

时间限制: 1 Sec 内存限制: 128 MB

提交: 59 解决: 2

[提交][状态][讨论版] [Edit] [TestData]

题目描述

厂源在街头表演悠悠球赚了好多钱,并且给她的女神买了礼物,现在的厂源又叫做厂百万,他给你一个自然数n,它的位数小于等于一百万,现在你要做的就是求出这个数除10003之后的余数。

输入

第一行有一个整数m(1<=m<=8),表示有m组测试数据;

随后m行每行有一个自然数n。

输出

输出n整除10003之后的余数,每次输出占一行。

样例输入

3

4

5

465456541

样例输出

4

5

6948

注意:因为是有一百万,所以没有那么简单。

#include <stdio.h>
#include <string.h>

const int MAX = 1000010;
int quyu(char a[], int m)
{
int l = strlen(a);
int s = 0;
for(int i = 0; i < l; i++)
{
s = 10*s + (a[i] - '0');//直接模拟除法,每次累计取余
s %= m;
}
return s;
}

int main()
{
char a[MAX];
int m;
scanf("%d", &m);
while(m--)
{
scanf("%s", &a);
int k = quyu(a, 10003);
printf("%d\n", k);
}
return 0;
}


问题 C: 耿小霞表白记

时间限制: 1 Sec 内存限制: 128 MB

提交: 176 解决: 10

[提交][状态][讨论版] [Edit] [TestData]

题目描述

耿小霞想要给男神表白,这是起因。

有一天,耿小霞邀请她男神去她家里教她编程,由于男神敲代码太帅,所以耿小霞把持不住,准备当场表白。

但是表白不能没有花吧?耿小霞想要有一个浪漫的开始,所以想要趁男神安静敲代码的时候出去买一束花,已知耿小霞家旁边有一家花店,时间是下午,贤惠的耿小霞还想要给男神露一手,所以就还要去一趟菜市场,其格局如图所示(中间是耿小霞的家,1为花店,2为菜市场):

由于耿小霞想要早点表白,所以快点买完东西回去就好了, 已知家和花店、花店和菜市场、菜市场和家两两之间的距离a,b,c,求耿小霞经过的最短的距离是多少?

输入

输入一组数据,包括三个数a, b, c(a,b,c都在整形范围内,注意两个int类型相加可能会超过int类型)

a代表家和花店的距离

b代表花店和菜市场的距离

c代表菜市场和家之间的距离

输出

输出耿小霞从家出发经过花店和菜市场再回家所需要走的最小路程。

样例输入

10 20 30

样例输出

60

思路:这题不需要考虑三角形,直接求出2a+2b,a+b+c,2a+2c,2b+2c最小的值就好了。

还有,两个int类型相加会超过int类型,还是要用int

代码:

#include<iostream>
using namespace std;
long long a,b,c;
main()
{
cin>>a>>b>>c;
cout<<min(min(a+b+c,2*(a+c)),min(2*(b+c),2*(a+b)));
}


问题 D: 进制转换

时间限制: 1 Sec 内存限制: 128 MB

提交: 71 解决: 3

[提交][状态][讨论版] [Edit] [TestData]

题目描述

首先,这并不是普通的进制转换题,其次,万一很简单呢?

耿小霞终于追到了她的男神,但是她的男神喜欢八进制,耿小霞却喜欢十六进制,为了让她男神开心,所以耿小霞决定写一个程序,将所有的十六进制数转换成八进制,使他们喜欢的数得到统一。

输入

输入的第一行有一个正整数n(1<=n<=10).

接下来的n行,每行一个由0~9、大写字母A~F组成的字符串,表示要转化的十六进制正整数,每个十六进制数长度不超过100000。

输出

输出n行,每行输入对应的八进制正整数。

【注意】

输入的16进制数不会有前导0,比如012A

输出的8进制数也不会有前导0

样例输入

2

39

123ABC

样例输出

71

4435274

提示

先将16进制数转换成某进制数,再由某进制数转换成八进制数。

思路:先将16进制转换成2进制,一个数字对应二进制四位,再将二进制转换成8进制,每三位对应一个数字。这是比较优的一个方法,其余的容易超时。

代码:

#include <iostream>
#include <string>
using namespace std;

int main()
{
int n;
cin>>n;
for(int k=1;k<=n;k++)
{
string s1,s2;//将string转换成char数组是一样的效果
cin>>s1;
s2="";
for(int i=0;i<s1.length();i++)
{
switch(s1[i])
{
case '0':s2+="0000";break;//string的加号运算可以用strcat代替,表示字符串拼接
case '1':s2+="0001";break;
case '2':s2+="0010";break;
case '3':s2+="0011";break;
case '4':s2+="0100";break;
case '5':s2+="0101";break;
case '6':s2+="0110";break;
case '7':s2+="0111";break;
case '8':s2+="1000";break;
case '9':s2+="1001";break;
case 'A':s2+="1010";break;
case 'B':s2+="1011";break;
case 'C':s2+="1100";break;
case 'D':s2+="1101";break;
case 'E':s2+="1110";break;
case 'F':s2+="1111";break;
default:break;
}
}
int len=s2.length();

if(len%3==1)
s2="00"+s2;
else if(len%3==2)
s2="0"+s2;
int flag=0;
for(int i=0;i<=s2.length()-3;i+=3)
{
int num=4*(s2[i]-'0')+2*(s2[i+1]-'0')+(s2[i+2]-'0');//将ascII码转化成相应的数字
if(num)
flag=1;
if(flag)
cout<<num;
}
cout<<endl;
}
return 0;
}


问题 E: 恶龙传说

时间限制: 1 Sec 内存限制: 128 MB

提交: 32 解决: 5

[提交][状态][讨论版] [Edit] [TestData]

题目描述

“河海有恶龙,群起而除之”
很久很久以前,河海有m条恶龙,每一条恶龙都有自身的能力值k1。恶龙们占据了河海大学,还抢走了河海小公举Tinyeh,为了从恶龙手中救走Tinyeh,Gray骑士团派出 n个骑士,每一个骑士的能力值为k2,每一个骑士只能杀死能力值比自己低的恶龙,但是骑士使用自己的能力是要付同自己能力值一样的钱的,而且一个骑士只能杀一条龙!!!!!!!
Gray骑士团为了节约开支,他们想知道自己最少需要付的钱是多少。


输入

第一行:两个数字,m,n(1 <= m, n <= 20 00),分别表示恶龙的数量和骑士的数量。

接下来又m+n行,前m行表示恶龙的能力值k1,后面n行表示骑士的能力值k2。

输出

如果骑士可以杀死全部恶龙,则输出需要的最小金币数s(输出保证在整形范围内)

如果无法杀死全部恶龙,则输出”Tinyeh Death!”

样例输入

2 3

5

4

7

8

4

样例输出

11

提示

输入:

2 1

5

5

10

输出:

Tinyeh Death!

思路:先排序,再比较。

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <algorithm>

#define N 20000
int a1[N+5], a2[N+2];//a1,a2分别储存恐龙的能力值和骑士的能力值
using namespace std;

int main()
{
int m, n, i;
scanf("%d%d", &m, &n);

for(i = 0; i < m; i++)
{
scanf("%d", &a1[i]);
}

for(i = 0; i < n; i++)
{
scanf("%d", &a2[i]);
}

sort(a1, a1+m);//此处换成冒泡排序,表示分别对a1,a2排序
sort(a2, a2+n);

if(m > n)
{
printf("Tinyeh Death!\n");
}

else
{
int s = 0, j = 0;
for(i = 0; i < n; i++)
{
if(a2[i] >= a1[j])
{
s += a2[i];
j++;
}

if(j == m)
break;
}

if(j == m)
printf("%d\n", s);
else
{
printf("Tinyeh Death!\n");
}
}

return 0;
}


问题 F: 理书

时间限制: 1 Sec 内存限制: 128 MB

提交: 37 解决: 3

[提交][状态][讨论版] [Edit] [TestData]

题目描述

BigSB买了好多本不同的书,决定把书理一理。他想要改变过去书的结构,即每本书都不在原来的位置,问聪明的BigSB总共有多少种不同重组方法。

输入

第一行输入一个数据k,表示有k组数据,接下来的k行,每行输入为一个整数N(1 <= N <= 20),代表书的数目

输出

对于每一个输入数据,每行输出一个整数,代表总共的重组方案数

样例输入

2

1

2

样例输出

0

1

思路:错排问题,感兴趣的自己去百度错排。

公式: a[i]=(a[i-1]+a[i-2])*(i-1);

#include<stdio.h>

int main()
{
int i,n,T;
long long a[21]={0,0,1};
for(i=3;i<=20;++i)
{
a[i]=(a[i-1]+a[i-2])*(i-1); //错排公式--不懂的可以参考信封装错的那题
}
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
printf("%lld\n",a
);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: