引言
针对初学者,每日练习几个题,快速上手C语言。第十一天。(连续更新中)
采用在线OJ的形式
什么是在线OJ?
在线判题系统(英语:Online Judge,缩写OJ)是一种在编程竞赛中用来测试参赛程序的在线系统,也可以用于平时的练习。
乐乐今天很想和你玩游戏 (今天的题会有几个难度,不要灰心,我做起来也不是很顺利)
1.小乐乐与进制转换
cpp
代码一:
#include <stdio.h>
int main()
{
int n = 0;
int arr[40] = {0};
int i = 0;
scanf("%d", &n);
while(n)
{
arr[i++] = n%6;
n/=6;
}
for(i--; i>=0; i--)
{
printf("%d", arr[i]);
}
return 0;
}
代码二:(递归)
#include<stdio.h>
void print(int x)
{
if(x>5)
{
print(x/6);
}
printf("%d",x%6);
}
int main()
{
int n=0;
scanf("%d",&n);
print(n);
return 0;
}
解析:
考察对进制的理解。
这里简单说一下,如十进制:12345,每个位置都有自己的权重,5 的权重是10^0,4的权重是10^1,3的权重是10^2,2的权重是10^3,1的权重是10^4,所以
1234 等于 1 * 10^4 + 2 * 10^3 + 3 * 10^2 + 2 * 10^1 + 1 * 10^0;
所以 六进制的10 = 0 * 6^0 + 1 * 6^1 = 十进制的6;
六进制的320 = 0 * 6^0 + 2 * 6^1 + 3 * 6^2 = 十进制的120
那么怎么十进制转换成六进制呢:
仔细看: 120 % 6 = 0; 120 / 6 = 20;
20 % 6 = 2; 20 / 6 = 3;
3 % 6 = 3;
会发现: 023 正好是 320 的倒叙。发现了这个规律就可以写代码了,这也是为什么可以用递归解决,因为是倒叙打印。
2.小乐乐求和
cpp
#include <stdio.h>
//代码1(暴力解法)
int main()
{
long long i = 0;
long long sum = 0;
long long n = 0;
scanf("%lld", &n);
for(i=1; i<=n; i++)
{
sum += i;
}
printf("%lld\n", sum);
return 0;
}
//代码2(用等差数列求和公式)
int main()
{
long long n = 0;
scanf("%lld", &n);
printf("%lld", (1+n)*n/2);
return 0;
}
解析:这个题很简单。
**3.**小乐乐定闹钟
cpp
#include <stdio.h>
int main()
{
int h = 0;
int m = 0;
int k = 0;
scanf("%d:%d %d", &h, &m, &k);
h = ((m+k)/60+h)%24; // 错误解法:h = ((h + k / 60 ) % 24;
//因为m 和 k的余数可以合成1小时
m = (m+k)%60;
printf("%02d:%02d\n", h, m);
return 0;
}
解析:
h后面%24是处理大于24小时的情况。
**4.**小乐乐排电梯
cpp
#include <stdio.h>
int main()
{
int n = 0;
scanf("%d", &n);
printf("%d\n", n/12*4 + 2);
return 0;
}
解析:很简单,读懂题意就能做出来
**5.**小乐乐与欧几里得
cpp
#include <stdio.h>
//暴力求解:
//耗时太久,不满足条件
int main()
{
long long n = 0;
long long m = 0;
long long tmp = 0;
scanf("%lld %lld", &n, &m);
long long max = m>n?n:m;
while(max) //找最大公约数
{
if(m%max==0 && n%max==0)
{
break;
}
max--;
}
long long min = m>n?m:n;
while(min) //找最小公倍数
{
if(min%m==0 && min%n==0)
{
break;
}
min++;
}
printf("%lld\n", max+min);
return 0;
}
//辗转相除法 (希望你可以记住这个解法)
int main()
{
long long n = 0;
long long m = 0;
long long tmp = 0;
scanf("%lld %lld", &n, &m);
int a = n;
int b = m;
while(tmp=a%b) //求最大公约数
{
a = b;
b = tmp;
}
long long t = m*n / b; //求最小公倍数
printf("%lld\n", b+t);
return 0;
}
解析:代码一暴力求解很费时间
代码二:辗转相除法,用个例子来模拟一下:a = 24 b = 18
tmp = 24 % 18 = 6;
a = 18 , b = 6;
tmp = 18 % 6 = 0;
6 就是最大公约数。别问我为什么,我也是学到的
求最小公倍数:t = 24 * 18 / 6 = 72;
6.小乐乐改数字
cpp
#include <stdio.h>
#include <math.h>
int main()
{
int n = 0;
int ret = 0;
scanf("%d", &n);
int i = 0;
while(n)
{
//计算每一位
int w = n%10;
//判断奇偶数
if (w % 2 == 1)
w = 1;
else
w = 0;
ret += w * pow(10, i);
n/=10;
i++;
}
printf("%d", ret);
return 0;
}
解析:从低位向高位移动一个一个判断,最后对应位置乘上所对应的权重。
pow(n, m)所得结果是n^m。
7.小乐乐走台阶
cpp
代码一:递归
#include <stdio.h>
int fib(int n)
{
if(n<=2)
return n;
else
return fib(n-1)+fib(n-2);
}
int main()
{
int n = 0;
scanf("%d", &n);
printf("%d\n", fib(n));
return 0;
}
解析:
- 如果只有1级台阶,那显然只有一种跳法
- 如果有2级台阶,那么就有2种跳法,一种是分2次跳。每次跳1级,另一种就是一次跳2级
- 如果台阶级数大于2,设为n的话,这时我们把n级台阶时的跳法看成n的函数,记为,第一次跳的时候有2种不同的选择:一是第一次跳一级,此时跳法的数目等于后面剩下的n-1级台阶的跳法数目,即为,二是第一次跳二级,此时跳法的数目等于后面剩下的n-2级台阶的跳法数目,即为,因此n级台阶的不同跳法的总数为,不难看出就是斐波那契数列
作者:lkkwxy
链接:剑指Offer算法题-青蛙跳台阶的问题 - 简书 (jianshu.com)
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处
代码二:用动态规划来做。
参考代码:
cpp
#include<stdio.h>
const int N = 35;
int dp[N];
int main()
{
int n = 0;
scanf("%d", &n);
dp[1] = 1; dp[2] = 2;
for(int i = 3; i <= n; i++)
{
dp[i] = dp[i - 1] + dp[i - 2];
}
printf("%d", dp[n]);
return 0;
}
解析:
1.状态表示:dp[i] 表示 走到第 i 个台阶时此时的方案数。
2.状态转移方程:dp[i] = dp[i - 1] + dp[i - 2]; 解释:当走到第i个台阶时,有两种方法可以到第i个台阶,分别是从i - 1的位置跳过去,i - 2的位置条过去,所以i - 1 和 i - 2位置对应的方案数相加,就是 i 位置的方案数。
3.初始化:因为i - 1和 i - 2可能会越界,所以初始化dp[1] = 1;dp[2] = 2;
4.填表顺序:从左往右填。因为要用前两个格子对应的方案数。
5结果:dp[n] 就表示跳到n节台阶的方案数。
8.小乐乐与序列
cpp
#include <stdio.h>
int main()
{
int n = 0;
int arr[100000] = {0};
int i = 0;
int tmp = 0;
scanf("%d", &n);
for(i=0; i<n; i++)
{
scanf("%d", &tmp);
arr[tmp] = tmp;
}
for(i=0;i<100000;i++)
{
if(arr[i] != 0)
printf("%d ", arr[i]);
}
return 0;
}
解析:
因为题目的数据是1 到 1e5 ,所以可以用数组对应的下标来存储对应位置的值,这样就达到了去重的效果,最后从左往右找到不是0的值打印就可以了(因为题目说了是正整数,所以不用开始的时候对数组初始化)
9. 小乐乐与字符串
cpp
#include <stdio.h>
//这个题的难度在于理解题目的意思
//不是连续的子串
//只要在字符串中找到几个字符能组合成子串就算是"子串"
int main()
{
char str[8000] = {0};
int count = 0;
scanf("%s", str);
char * p = str; //把数组的地址交给p
long long c = 0;
long long ch = 0;
long long chn = 0;
while(*p)
{
if(*p == 'C')
c++;
else if(*p == 'H')
ch+=c; //因为是要所有情况,所以是加等于。
else if(*p == 'N')
chn += ch;
p++; //接着下一位
}
printf("%lld\n", chn);
return 0;
}
解析:
1. 这个题中的子串可以是不连续的
2. ch的个数其实和前面出现的c的个数有关,chn的个数和n之前ch的个数有关。
10.小乐乐找最大数
cpp
#include <stdio.h>
int main()
{
int arr[4] = {0};
int i = 0;
for(i=0; i<4; i++)
{
scanf("%d", &arr[i]);
}
//假设
int max = arr[0];
for(i=1; i<4; i++)
{
if(arr[i]> max)
{
max = arr[i];
}
}
printf("%d\n", max);
return 0;
}
解析:非常简单。找最大是就可以了
**11.**小乐乐转换成绩
cpp
#include <stdio.h>
int main() {
int score = 0;
scanf("%d", &score);
if (score < 0 || score > 100)
printf("F\n");
else if (score >= 90 && score <= 100)
printf("A\n");
else if (score >= 80 && score <= 89)
printf("B\n");
else if (score >= 70 && score <= 79)
printf("C\n");
else if (score >= 60 && score <= 69)
printf("D\n");
else
printf("E\n");
return 0;
}
解析:按着题意做就可以了
**12.**小乐乐计算函数
cpp
#include <stdio.h>
int max3(int a, int b, int c) {
int max = a;
if (b > max)
max = b;
if (c > max)
max = c;
return max;
}
// int max3(int a, int b, int c) { //也可以达到效果
// int max = a > b ? a : b;
// return max > c ? max : c;
// }
int main() {
int a = 0;
int b = 0;
int c = 0;
scanf("%d %d %d", &a, &b, &c);
float m = ((float)max3(a + b, b, c) / (max3(a, b + c, c) + max3(a, b, b + c)));
printf("%.2f\n", m);
return 0;
}
解析:先把max3函数写出来,然后对应位置的值运算即可。