A:圆的直径、周长和面积
sol: 题目说输入只有一行,没说多组测试数据,所以连循环输入都不用。用double和float都能AC,但是一般碰到小数的题目建议使用double,因为double更加精确。
#include <cstdio>
#include <cmath>
using namespace std;
const double PI = 3.1415926;
int main() {
double r, d, p, s;
scanf("%lf", &r);
d = 2 * r;
p = d * PI;
s = r * r * PI;
printf("%.2lf %.2lf %.2lf\n", d, p, s);
return 0;
}
B:07的游泳时间
sol: 先直接拿第二个时间的小时和分减第一个时间的小时和分,得到的小时一定不小于0,得到的分可能小于0,那么我们只要处理一些负的分就好了,如果分为负数,分加上60,小时减1。
#include <cstdio>
using namespace std;
int main() {
int a, b, c, d;
while (~scanf("%d%d%d%d", &a, &b, &c, &d)) {
int e = c - a;
int f = d - b;
if (f < 0) {
f += 60;
e -= 1;
}
printf("%d %d\n", e, f);
}
return 0;
}
ps: ~scanf("%d%d%d%d", &a, &b, &c, &d) 和 scanf("%d%d%d%d", &a, &b, &c, &d) != EOF 作用一样
C:小明A+B
sol: A + B 很好算,这题只要将结果保留最后两位就好了, 那么我们可以通过对100取余得到最后两位。
#include <cstdio>
using namespace std;
int main() {
int t, a, b;
scanf("%d", &t);
while (t--) {
scanf("%d%d", &a, &b);
a %= 100;
b %= 100;
printf("%d\n", (a + b) % 100); // 取余的优先级和乘除一样高
}
return 0;
}
ps: a %= 100; 和 b %= 100;这两句不加也可以通过这题,但是按照题目要求是必须加上的,因为题目中说(A和B均在int型可表示的范围内). 大家都知道int范围是有上限的,太大的数字是装不了的。A、B都在int型可表示范围,那么如果A和B都是int的边界,A + B就会超出int可表示范围。比如输入两个2147483647。同学们可以测一下自己的代码能不能得到94这个结果。当然也可以采用长整型long long来解决这个问题。
D:幸运数
sol: 这一题就是一个数位分离,可以用循环把年月日的所以位数分离出来,分出一个消一个具体的还是看代码理解吧
#include <cstdio>
using namespace std;
int main() {
int a, b, c; // int sum = 0;
while (~scanf("%d%d%d", &a, &b, &c)) {
int sum = 0;
while (a != 0) {
sum += a % 10; // 取出a的个位
a /= 10; // 消除a的个位
}
while (b != 0) {
sum += b % 10; // 取出b的个位
b /= 10; // 消除b的个位
}
while (c != 0) {
sum += c % 10; // 取出c的个位
c /= 10; // 消除c的个位
}
printf("%d\n", sum % 10);
}
return 0;
}
ps: 比较容易出现的错误是像我上面注释的那样把sum = 0写到了外面,要注意我们的这道题目是多组测试数据,如果sum = 0; 写在了while的外面,第一组数据的sum是等于0,但是第二次进入循环sum就会保留第一组数据的结果。所以要写在循环里面,每次进入循环都重新把sum的值设置成0。
E:汉堡包
sol: 输入n个数,同时判断哪些数是不超过100的,再把所有不超过100的数加起来。
#include <cstdio>
using namespace std;
int main() {
int n, m, sum = 0;
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
scanf("%d", &m);
if (m <= 100) sum += m;
}
printf("%d\n", sum);
return 0;
}
F:谁拿了最多的奖学金
sol: 这题就是题目长了点,if多了点,求出每个同学的奖学金数量,再和之前奖学金最多的同学比较一下就好了
#include <cstdio>
using namespace std;
int main() {
int n, ans = 0;
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
int a, b, c, sum = 0;
scanf("%d%d%d", &a, &b, &c);
if (a >= 80 && c >= 1) sum += 8000;
if (a >= 85 && b >= 80) sum += 4000;
if (a >= 90) sum += 2000;
if (sum > ans) ans = sum;
}
printf("%d\n", ans);
return 0;
}
G:最右边的数字
作为压轴题,当然是要带点坑的。很多同学直接求了n的n次方然后对10取余。但是我在上面的C题也提到了,int范围有限。n的最大范围是1000,那么1000的1000次方想一想就知道是个天文数字,远超过int的极限值。有同学考虑到int范围问题然后改用了long long,但是long long的极限范围大概是int范围的平方,也是无法装那么大的一个数了。那么这个问题该怎么解决呢?
sol1: 用同余定理。可以自己去百度里查一下,大概就是说a * b % p我们可以转化成((a % p) * (b % p)) % p。举个例子34 * 101 % 8 -> ((34 % 8) * (101 % 8)) % 8 -> 2 * 5 % 8 ->2。
#include <cstdio>
using namespace std;
int main() {
int t, n;
scanf("%d", &t);
while (t--) {
scanf("%d", &n);
int ans = 1;
for (int i = 1; i <= n; i++) {
ans *= n;
ans %= 10;
}
printf("%d\n", ans);
}
return 0;
}
sol2: 找规律。
昨天AK的4位同学里,有同学想到了比较新奇的另一种解法。先来看一下他的代码
#include <cstdio>
#include <iostream>
using namespace std;
int main() {
int n;
while (cin >> n) {
while (n--) {
int m;
cin >> m;
if (m % 10 == 1) {
cout << 1 << endl;
} else if (m % 10 == 2) {
int i[] = {6, 2, 4, 8};
cout << i[(m % 4)] << endl;
} else if (m % 10 == 3) {
int i[] = {1, 3, 9, 7};
cout << i[(m % 4)] << endl;
} else if (m % 10 == 4) {
int i[] = {6, 4};
cout << i[(m % 2)] << endl;
} else if (m % 10 == 5) {
cout << 5 << endl;
} else if (m % 10 == 6) {
cout << 6 << endl;
} else if (m % 10 == 7) {
int i[] = {1, 7, 9, 3};
cout << i[(m % 4)] << endl;
} else if (m % 10 == 8) {
int i[] = {6, 8, 4, 2};
cout << i[(m % 4)] << endl;
} else if (m % 10 == 9) {
int i[] = {1, 9};
cout << i[(m % 2)] << endl;
} else if (m % 10 == 0) {
cout << 0 << endl;
}
}
}
return 0;
}
这份代码用到了还没有讲过的关于数组的内容,大概就是说当m的个位是1的时候,m的m次方个位总是1;当m个位是2的时候,m的m次方个位总是在6, 2, 4, 8这几个数里面循环。。。。。。
其实m的m次方的个位总是在0, 1, 4, 7, 6, 5, 6, 3, 6, 9, 0, 1, 6, 3, 6, 5, 6, 7, 4, 9这几个数里循环,下面是我的代码
#include <cstdio>
using namespace std;
int a[] = {0, 1, 4, 7, 6, 5, 6, 3, 6, 9, 0, 1, 6, 3, 6, 5, 6, 7, 4, 9};
int main() {
int t, n;
scanf("%d", &t);
while (t--) {
scanf("%d", &n);
printf("%d\n", a[n % 20]);
}
return 0;
}
因为没有讲过数组,这边还有一份swtich的代码来帮助大家理解
#include <cstdio>
using namespace std;
int main() {
int t, n;
scanf("%d", &t);
while (t--) {
scanf("%d", &n);
switch (n % 20) {
case 0 : printf("0\n"); break;
case 1 : printf("1\n"); break;
case 2 : printf("4\n"); break;
case 3 : printf("7\n"); break;
case 4 : printf("6\n"); break;
case 5 : printf("5\n"); break;
case 6 : printf("6\n"); break;
case 7 : printf("3\n"); break;
case 8 : printf("6\n"); break;
case 9 : printf("9\n"); break;
case 10 : printf("0\n"); break;
case 11 : printf("1\n"); break;
case 12 : printf("6\n"); break;
case 13 : printf("3\n"); break;
case 14 : printf("6\n"); break;
case 15 : printf("5\n"); break;
case 16 : printf("6\n"); break;
case 17 : printf("7\n"); break;
case 18 : printf("4\n"); break;
case 19 : printf("9\n"); break;
}
}
return 0;
}
比较sol1和sol2哪种方法好呢?很多同学可能觉得sol1简单,比较好。但其实sol2这种方法更好,这道题的原题是台州OJ1316题,那么对于那题n的范围是1000000000,用sol1虽然结果正确但是会超时,但是用sol2求n的n次方不用循环n次,计算一次就能得到结果。所以如果对n的范围进行加大,可能只有sol2才能通过题目。