第一次练习总结
第一次练习总结
问题:
- 做的人有些少,做够3个题AC可以得到平时成绩
- 有助教反映存在抄代码的问题.注意只抄代码不能提高编程水平
- 而且考试的时候没的抄 平时练习的时候一定打好基础:)
AC代码(仅供参考 别照抄)
A 一道水题
- 注意格式控制字符
%
在printf
的format
字符串中要写成%%
- 这是个送分题:)
#include <stdio.h>
int main(){
int a,b;
scanf("%d%d",&a,&b);
printf("%d %% %d = %d",a,b,a % b);
return 0;
}
B 分数约分
- (我的)思路是先处理符号,然后全部取绝对值,然后求最大公约数
- 下面代码用了辗转相除法
教程:https://baike.baidu.com/item/欧几里得算法/1647675
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <ctype.h>
#include <time.h>
#pragma warning(disable:4996)
int gcd(int m,int n){
return m % n == 0?n:gcd(n,m % n);
}
int main(){
int m,n,sign;
while(~scanf("%d%d",&m,&n)){
sign = 0;
//preprocess
if(n < 0){
n = -n;
sign = 1;
if(m < 0){
m = -m;
sign = 0;
}
else if(m == 0){
puts("0");
continue;
}
}
else if(n > 0){
if(m < 0){
m = -m;
sign = 1;
}
else if(m == 0){
puts("0");
continue;
}
}
else{//n==0
continue;
}
//end preprocess m>0 n>0
int g = gcd(m,n);
int a = m / g;
int b = n / g;
int res = a / b,mod = a % b;
if(res){
if(mod){
if(sign){
printf("-%d-%d/%d\n",res,mod,b);
}
else{
printf("%d+%d/%d\n",res,mod,b);
}
}
else{
if(sign){
putchar('-');
}
printf("%d\n",res);
}
}
else{
if(mod){
if(sign){
printf("-%d/%d\n",mod,b);
}
else{
printf("%d/%d\n",mod,b);
}
}
}
}
return 0;
}
C 字母频率统计
- 如需使用
islower
,isupper
,tolower
,toupper
记得#include <ctype.h>
- 思路:不停的读字符,如果读到是大写字母直接计数,如果是小写字母转换成大写字母再计数.
- 浮点数除法 关注输出要求.
#include <stdio.h>
#include <ctype.h>
int main(){
int c,i;
double rate;
int total = 0;
int a[26] = {0};
while((c = getchar()) != EOF){
if(islower(c))c = toupper(c);
if(c >= 'A' && c <= 'Z'){
a[c - 'A']++;
total++;
}
}
for(i = 0;i < 26;i++){
if(a[i] > 0){
rate = (double)a[i] / total;
printf("%c %.2lf%%\n",i + 'A',rate*100);
}
}
return 0;
}
D 水君的价格
- 热身赛好像有个类似的题目 注意数据范围和格式化输出的写法
- 只用算
*2
就好了 最后补0
#include <stdio.h>
int main(int argc, const char * argv[]) {
long long n;
long long unsigned x;
while (scanf("%lld",&n)!=EOF) {
if (n>0) {
x=2*n;
printf("%llu00\n",x);
} else if(n<0){
x=-n;
x=2*x;
if (x==0) {
puts("-1844674407370955161600");
}else{
printf("-%llu00\n",x);
}
}else if (n==0){
printf("0\n");
}
}
return 0;
}
E 漏沙漏
- 逻辑有些恶心.核心是找规律确定字符的出现位置.(规律找到就舒服些)
- 奇数和偶数分别处理
#include <stdio.h>
int main(){
int n,m,i,j,h;
scanf("%d%d",&n,&m);
h = n % 2 == 0?n / 2:n / 2 + 1;
for(j = 0;j < n;j++){
putchar('*');
}
putchar('\n');
for(i = 1;i < h;i++){
for(j = 0;j < n - i - 1;j++){
if(j < i)putchar(' ');
else if(j == i)putchar('*');
else{
putchar(i <= m?' ':'*');
}
}
putchar('*');putchar('\n');
}
for(i = 1;i < h;i++){
for(j = 0;j < (n % 2 == 0?h + i - 1:h + i - 2);j++){
if(i + j < h)putchar(' ');
else if(i + j == h)putchar('*');
else{
putchar(i < h - m?' ':'*');
}
}
putchar('*');putchar('\n');
}
for(j = 0;j < n;j++){
putchar('*');
}
putchar('\n');
}
F 电梯
题意是A坐电梯去找B.后面有比较大的数据 模拟会超时
第一种解法:
- 如果A和B在同一层,结论显然.
- 考虑循环 如果有\(m\)层,循环节长度是\(2m-2\) 利用取mod可以确定当前状态.
- 先考虑A坐上电梯有3种情况
- A找B 有4种情况 分别处理即可(各位可以想想是哪些情况)
#include <stdio.h>
int main(){
int m,s,t,n,ans = 0;
scanf("%d%d%d%d",&m,&s,&t,&n);
int loop = 2 * m - 2;//电梯循环周期
int current = n % loop + 1;//电梯在第n秒的位置
if(s == t){//AB同一层
ans = n;
}
else{
if(current <= s){//电梯向上运动能接到A
;
}
else if(current > s && current <= (loop + 2 - s)){//电梯向下运动能接到A
s = loop + 2 - s;
}
else{//这趟不行 下一趟电梯向上运动能接到A
s += loop;
}
//4种情况
if(s <= t){
;
}
else if(s <= (2 * m - t)){
t = loop + 2 - t;
}
else if(s <= (2 * m + t)){
t += loop;
}
else{
t = 2 * loop + 2 - t;
}
ans = n + (t - current);
}
printf("%d",ans);
return 0;
}
另解:
(这个是我搬运出题julao给的做法 原理他写在注释里了)
#include <stdio.h>
#include <math.h>
long long n,maxv,s,t,n,mm;
int main(){
scanf("%lld",&maxv);
mm=(maxv-1)*2;//电梯上下一个周期的时间
scanf("%lld %lld %lld",&s,&t,&n);
if(s==t){
printf("%lld\n",n);//小迷弟那都不用去直接到包房
}
else{
long long tmp1,tmp2;
if(s<t) tmp1=s-1;//电梯从1楼向上接到小迷弟
else tmp1=mm+1-s;//电梯从maxv层向下接到小迷弟
long long tmp3=n/mm*mm+tmp1;//n秒之前电梯跑过n/mm*mm次轮回 又花了tmp1的时间接小迷弟
if(tmp3<n) tmp2=tmp3+mm;//但是仍有可能小于n 如果小于n必须加个周期才能保证在小迷弟出现之后接到小迷弟
else tmp2=tmp3;
printf("%lld\n",tmp2+abs(s-t));//再走两者的距离
}
return 0;
}
G
- 很容易漏掉
'0'
- 下面给2种做法
最朴素的办法是 分 情 况 一 个 个 列
为了增强代码可读性 建议不要照着下面的来
65
你就写成'A'
是可以的
#include <stdio.h>
int main(){
for(;;){
char ch = getchar();
if(ch == -1)break;
if(!(ch >= 0x20 && ch < 0x7f))continue;//处理掉特殊字符
if(ch == '1')
printf("1");
else if(ch == '2')
printf("2");
else if(ch == '3')
printf("3");
else if(ch == '4')
printf("4");
else if(ch == '5')
printf("5");
else if(ch == '6')
printf("6");
else if(ch == '7')
printf("7");
else if(ch == '8')
printf("8");
else if(ch == '9')
printf("9");
else if(ch == '0')
printf("0");
else if((ch >= 65 && ch <= 90) || (ch >= 97 && ch <= 122)){
if((ch >= 65 && ch <= 67) || (ch >= 97 && ch <= 99))
printf("2");
else if((ch >= 68 && ch <= 70) || (ch >= 100 && ch <= 102))
printf("3");
else if((ch >= 71 && ch <= 73) || (ch >= 103 && ch <= 105))
printf("4");
else if((ch >= 74 && ch <= 76) || (ch >= 106 && ch <= 108))
printf("5");
else if((ch >= 77 && ch <= 79) || (ch >= 109 && ch <= 111))
printf("6");
else if((ch >= 80 && ch <= 83) || (ch >= 112 && ch <= 115))
printf("7");
else if((ch >= 84 && ch <= 86) || (ch >= 116 && ch <= 118))
printf("8");
else if((ch >= 87 && ch <= 90) || (ch >= 119 && ch <= 122))
printf("9");
}
else printf("1");
}
return 0;
}
当然为了省事 这样也可
注意包含ctype.h
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <ctype.h>
#include <time.h>
int ch2key[30] = {2,2,2,3,3,3,4,4,4,5,5,5,6,6,6,7,7,7,7,8,8,8,9,9,9,9};
int main(){
for(;;){
char ch = getchar();
if(ch == EOF){
break;
}
else{
if(isdigit(ch)){
putchar(ch);
}
else if(islower(ch)){
ch = toupper(ch);
putchar('0' + (ch2key[ch - 'A']));
}
else if(isupper(ch)){
putchar('0' + (ch2key[ch - 'A']));
}
else if(isprint(ch)){
putchar('1');
}
}
}
return 0;
}
H 小兔子乖乖拔萝卜
- 思路是维护最大的3个数 需要注意更新数据时的操作顺序
- 来一组数据处理一组输出一次 不用纠结处理完所有的一次输出
#include<stdio.h>
int main()
{
int num,max1=0,max2=0,max3=0,t;
while(scanf("%d",&num) != EOF){
int n;
for(n=1;n<=num;n++){
scanf("%d",&t);
if(t>=max1) {
max3=max2;
max2=max1;
max1=t;
}
if( (t>=max2) && (t<max1) ){
max3=max2;
max2=t;
}
if( (t>=max3) && (t<max2) ) max3=t;
}
printf("%d %d %d\n",max1,max2,max3);
}
return 0;
}
- 各位可以想下 如果他给了
long long
也装不下的巨大整数 该怎么办
I 多边形对角线
- 注意数据范围和
long long
的使用方式 - 其实是数学问题
- 注意任意3条对角线不相交
- 每个交点必然是由2条对角线相交得到的.每条对角线对应2个顶点
- 问题转化成从n个点里面选4个不同点
#include <stdio.h>
int main(){
long long n;
scanf("%lld",&n);
printf("%lld",n*(n-1)*(n-2)*(n-3)/24);
return 0;
}
J 朵朵选靓号
- 可以开字符数组做,也可以用
long long
提取每一位做
参考代码:
#include<stdio.h>
int main(){
char a[20];
int i,f=0,h=0;i=0;
fgets(a,15,stdin);
for(i=0;i<=10;i++){
if(a[i]=='5')f++;
if(a[i]=='2'&&a[i+1]=='3'&&a[i+2]=='3')h=1;
}
if(h==1&&f<3)printf("Wonderful:%d",f);
else if(h==0)printf("Not good:%d",f);
else printf("Great:%d",f);
return 0;
}