3.4.4 例题一览与习题
得分(Score)
点击查看代码
#include<stdio.h>
#include<string.h>
char s[105];
int main()
{
int T;
scanf("%d", &T);
while(T--)
{
scanf("%s", s);
int len = strlen(s), cnt = 0, ans = 0;
for(int i = 0; i < len; i++)
{
if(s[i] == 'O')
{
cnt++;
ans += cnt;
}
else
cnt = 0;
}
printf("%d\n", ans);
}
return 0;
}
分子量(Molar Mass)
点击查看代码
#include<stdio.h>
#include<string.h>
#include<ctype.h>
char s[50];
double team[4] = {12.01, 1.008, 16.00, 14.01};//CHON
int mem[50];
int main()
{
int T;
scanf("%d", &T);
while(T--)
{
memset(mem, 0, sizeof(mem));
scanf("%s", s);
int i = 0;
while(i < strlen(s))
{
if(isalpha(s[i]))
{
char ch = s[i];
i++;
if(isalpha(s[i]) || i == strlen(s))
mem[ch - 'A']++;
else
{
int num = s[i] - '0';
i++;
while(!isalpha(s[i]) && i < strlen(s))
{
num = num*10 + s[i] - '0';
i++;
}
mem[ch - 'A'] += num;
}
}
}
printf("%.3f\n", mem['C'-'A']*team[0] + mem['H'-'A']*team[1] +mem['O'-'A']*team[2]+mem['N'-'A']*team[3]);
}
return 0;
}
数数字(Digit Counting)
点击查看代码
#include<stdio.h>
#include<string.h>
int num[15];
int main()
{
int T;
scanf("%d", &T);
while(T--)
{
int i;
scanf("%d", &i);
for(int j = 1; j <= i; j++)
{
int tem = j;
num[tem % 10]++;
while(tem / 10)
{
tem /= 10;
num[tem % 10]++;
}
}
for(int j = 0; j < 9; j++)
printf("%d ", num[j]);
printf("%d\n", num[9]);
memset(num, 0, sizeof(num));
}
return 0;
}
周期串(Periodic String)
点击查看代码
#include<stdio.h>
#include<string.h>
char s[105];
int main()
{
int T;
scanf("%d", &T);
while(T--)
{
scanf("%s", s);
int len = strlen(s), flag = 0;
for(int i = 1; i < (len+3)/2; i++)
{
if(len % i)
continue;
for(int j = 0; j < len - i; j++)
{
if(s[j] != s[i+j])
break;
if(j == len - i - 1)
{
printf("%d\n", i);
flag = 1;
}
}
if(flag)
break;
}
if(!flag)
printf("%d\n", len);
if(T)
printf("\n");
}
return 0;
}
注意:周期串的定义就要求这个周期是字符串长度的某个因数,如果没有判断是否为因数也就是是否可以整除,直接用本题的方法来解决,会出现abcab认为他的周期是3而不是5.因为我们在原先的判断方法中是逐个判断而不是整体判断,因此会出现这样的错误。
当有多组数据输出的时候一般每组数据之间需要间隔一个空行,但是最后一组数据不需要间隔一个空行。
谜题(Puzzle)
点击查看代码
#include<stdio.h>
#include<string.h>
char s[6][6];
char move[105];
int main()
{
char ch;
int kase = 0;
while((ch = getchar()) != 'Z')
{
if(ch == '\n')
if((ch = getchar()) == 'Z')
break;
if(kase)
printf("\n");
int x, y;
s[0][0] = ch;
for(int i = 1; i < 5; i++)
s[0][i] = getchar();
getchar();
for(int i = 1; i < 5; i++)
{
int fg = 1;
for(int j = 0; j < 5; j++)
if((s[i][j] = getchar()) == '\n')
{
s[i][j] = ' ';
fg = 0;
}
if(fg)
getchar();
}
for(int i = 0; i < 5; i++)
for(int j = 0; j < 5; j++)
if(s[i][j] == ' ')
{
x = i;
y = j;
}
int len = 0, flag = 0;
while((ch = getchar()) != '0')
{
if(ch == '\n')
continue;
move[len++] = ch;
}
for(int i = 0; i < len; i++)
{
if(move[i] == 'L')
{
if(y - 1 < 0)
{
flag = 1;
break;
}
s[x][y] = s[x][y-1];
y--;
s[x][y] = ' ';
continue;
}
if(move[i] == 'R')
{
if(y + 1 > 4)
{
flag = 1;
break;
}
s[x][y] = s[x][y+1];
y++;
s[x][y] = ' ';
continue;
}
if(move[i] == 'A')
{
if(x - 1 < 0)
{
flag = 1;
break;
}
s[x][y] = s[x-1][y];
x--;
s[x][y] = ' ';
continue;
}
if(move[i] == 'B')
{
if(x + 1 > 4)
{
flag = 1;
break;
}
s[x][y] = s[x+1][y];
x++;
s[x][y] = ' ';
continue;
}
}
if(flag)
{
printf("Puzzle #%d:\n", ++kase);
printf("This puzzle has no final configuration.\n");
}
else
{
printf("Puzzle #%d:\n", ++kase);
for(int i = 0; i < 5; i++)
{
for(int j = 0; j < 4; j++)
printf("%c ", s[i][j]);
printf("%c\n", s[i][4]);
}
}
}
return 0;
}
注意:在这些题目所在的UVAOJ中对于输出格式的要求非常严格,每行行末不能有空格并且相邻的多组数据之间必须通过换行符间隔,否则都会出现WA
纵横字谜的答案(Crossword Answers)
点击查看代码
#include<stdio.h>
#include<string.h>
char s[12][12];
int map[105][8];
int main()
{
int x, y, kase = 0;
while(true)
{
int cnt = 0;
memset(map, 0, sizeof(map));
scanf("%d", &x);
if(!x)
break;
if(kase)
printf("\n");
scanf("%d", &y);
for(int i = 0; i < x; ++i)
scanf("%s", s[i]);
for(int i = 0; i < x; ++i)
{
for(int j = 0; j < y; ++j)
{
if(s[i][j] == '*') continue;
if(i == 0)
{
cnt++;
map[cnt][0] = i;
map[cnt][1] = j;
map[cnt][3] = 1;
if(j == 0 || s[i][j-1] == '*')
map[cnt][2] = 1;
}
else if(j == 0)
{
cnt++;
map[cnt][0] = i;
map[cnt][1] = j;
map[cnt][2] = 1;
if(i == 0 || s[i-1][j] == '*')
map[cnt][3] = 1;
}
else if(s[i-1][j] == '*' || s[i][j-1] == '*')
{
cnt++;
map[cnt][0] = i;
map[cnt][1] = j;
if(j == 0 || s[i][j-1] == '*')
map[cnt][2] = 1;
if(i == 0 || s[i-1][j] == '*')
map[cnt][3] = 1;
}
}
}
printf("puzzle #%d:\n", ++kase);
printf("Across\n");
cnt++;
for(int i = 1; i < cnt; ++i)
{
if(map[i][2])
{
printf("%3d.", i);
int x1 = map[i][0];
int y1 = map[i][1];
for(int j = y1; j < y; j++)
{
if(s[x1][j] != '*')
{
printf("%c", s[x1][j]);
if(j == y - 1)
printf("\n");
}
else
{
printf("\n");
break;
}
}
}
}
printf("Down\n");
for(int i = 1; i < cnt; ++i)
{
if(map[i][3])
{
printf("%3d.", i);
int x1 = map[i][0];
int y1 = map[i][1];
for(int j = x1; j < x; j++)
{
if(s[j][y1] != '*')
{
printf("%c", s[j][y1]);
if(j == x-1)
printf("\n");
}
else
{
printf("\n");
break;
}
}
}
}
}
return 0;
}
注意:在UVA中如果有序号出现,一般需要右对齐且长度统一为3,否则就会出现PE
DNA序列(DNA Consensus String)
点击查看代码
#include<stdio.h>
#include<string.h>
char s[55][1005];
char ans[1005];
char num[1005][5];
int cmp[55];
int main()
{
int T;
scanf("%d", &T);
while(T--)
{
int m, n, max = 0;
memset(num, 0, sizeof(num));
memset(cmp, 0, sizeof(cmp));
scanf("%d%d", &m, &n);
for(int i = 0; i < m; i++)
scanf("%s", s[i]);
for(int i = 0; i < m; i++)
for(int j = 0; j < n; j++)
{
if(s[i][j] == 'A')
num[j][0]++;
if(s[i][j] == 'T')
num[j][1]++;
if(s[i][j] == 'G')
num[j][2]++;
if(s[i][j] == 'C')
num[j][3]++;
}
for(int i = 0; i < n; ++i)
{
if(num[i][0] >= num[i][1] && num[i][0] >= num[i][2] && num[i][0] >= num[i][3])
{
ans[i] = 'A';
max += num[i][0];
}
else if(num[i][3] >= num[i][1] && num[i][3] >= num[i][2] && num[i][3] >= num[i][0])
{
ans[i] = 'C';
max += num[i][3];
}
else if(num[i][2] >= num[i][1] && num[i][2] >= num[i][0] && num[i][2] >= num[i][3])
{
ans[i] = 'G';
max += num[i][2];
}
else if(num[i][1] >= num[i][2] && num[i][1] >= num[i][3] && num[i][1] >= num[i][4])
{
ans[i] = 'T';
max += num[i][1];
}
}
for(int i = 0; i < n; i++)
printf("%c", ans[i]);
printf("\n");
printf("%d\n", m * n - max);
}
return 0;
}
Hamming距离(汉明距离):就是指两个等长字符串之间对应位置但字符不同的个数
循环小数(Repeating Decimals)
点击查看代码
#include<stdio.h>
int cmp[10000000][2];
int main()
{
int a, b, ts = 1;
while(scanf("%d%d", &a, &b) == 2)
{
printf("%d/%d = ", a, b);
int len = 0, flag = 1;
do
{
printf("%d", a/b);
a = a - a/b*b;
}
while(a/b);
printf(".");
while(flag)
{
a *= 10;
cmp[len++][1] = a;
cmp[len-1][0] = a/b;
for(int i =0; i < len-1; i++)
{
if(cmp[i][1] == a)
{
flag = 0;
for(int j = 0; j < i; j++)
printf("%d", cmp[j][0]);
if((len - 1 - i) <51)
{
printf("(");
for(int j = i; j < len-1; j++)
printf("%d", cmp[j][0]);
printf(")\n");
}
else
{
printf("(");
for(int j = i; j < i+50; j++)
printf("%d", cmp[j][0]);
printf("...)\n");
}
printf(" %d = number of digits in repeating cycle\n\n", len - 1 - i);
break;
}
}
a = a - a/b*b;
}
}
return 0;
}
/*
1.do{}while();循环适合于先执行后判断的循环体
*/
注意:本题中的每一组数据都要求换行,依旧是说最后一组数据末尾要有两个换行,注意样例中的细节,以及第二行输出的时候需要空三个空格,%3d的意思是不足位的时候按照三位数输出,空白地方通过空格补齐,而不是会出现三个空格的意思
子序列(All in All)
点击查看代码
#include<stdio.h>
#include<string.h>
#define maxn 100005
char s1[maxn], s2[maxn];
int main()
{
while(scanf("%s%s", s1, s2) == 2)
{
int len1 = strlen(s1), len2 = strlen(s2), cnt = 0, sign = 0;
for(int i = 0; i < len1; i++)
{
for(int j = sign; j < len2; j++)
{
if(s1[i] == s2[j])
{
sign = j + 1;
cnt++;
break;
}
}
}
if(cnt == len1)
printf("Yes\n");
else
printf("No\n");
}
return 0;
}
盒子(Box)
点击查看代码
#include<stdio.h>
#include<string.h>
int rec[8][4];
int trec[8][4];
int main()
{
while(true)
{
int mem = 0, flag = 0;
memset(rec, 0, sizeof(rec));
if(!(scanf("%d%d", &rec[0][0], &rec[0][1]) == 2))
break;
for(int i = 1; i < 6; i++)
scanf("%d%d", &rec[i][0], &rec[i][1]);
for(int i = 0; i < 6; i++)
{
if(rec[i][2])
continue;
for(int j = i + 1; j < 6; j++)
{
if(!rec[j][2])
if((rec[i][0] == rec[j][0] && rec[i][1] == rec[j][1]) || (rec[i][1] == rec[j][0] && rec[i][0] == rec[j][1]))
{
rec[i][2] = 1;
rec[j][2] = 1;
trec[mem][0] = rec[i][0];
trec[mem][1] = rec[i][1];
mem++;
break;
}
}
}
if(mem != 3)
{
printf("IMPOSSIBLE\n");
continue;
}
if(trec[0][0] == trec[1][0])
if((trec[0][1] == trec[2][0] && trec[1][1] == trec[2][1]) || (trec[1][1] == trec[2][0] && trec[0][1] == trec[2][1]))
flag = 1;
if(trec[0][0] == trec[1][1])
if((trec[0][1] == trec[2][0] && trec[1][0] == trec[2][1]) || (trec[1][0] == trec[2][0] && trec[0][1] == trec[2][1]))
flag = 1;
if(trec[0][1] == trec[1][0])
if((trec[0][0] == trec[2][0] && trec[1][1] == trec[2][1]) || (trec[1][1] == trec[2][0] && trec[0][0] == trec[2][1]))
flag = 1;
if(trec[0][1] == trec[1][1])
if((trec[0][0] == trec[2][0] && trec[1][0] == trec[2][1]) || (trec[1][0] == trec[2][0] && trec[0][0] == trec[2][1]))
flag = 1;
if(flag)
printf("POSSIBLE\n");
else
printf("IMPOSSIBLE\n");
}
return 0;
}
/*
1.注意如果多重if后面的语句没有加上大括号的话,那么else是与最近的if配对的
2.本题程序思路上存在隐秘的漏洞,注意hack数据:1 2 1 2 1 2 1 2 1 1 1 1
*/
注意:这道题中的本人思路中存在非常隐秘的漏洞,那就是对于1 2 1 2 1 2 1 2 1 1 1 1的数据输出为IMPOSSIBLE,正解应该为POSSIBLE,造成的原因是因为如果长方体中有四个面的长短都一样的时候,此时的长方体不是唯一的,因为他存在两种情况,一前面的例子为例,他还可以是1 2 1 2 1 2 1 2 2 2 2 2,而对于其他的数据则这个长方体是唯一的,因此这边需要多判断一次才可以,简单的一次判断不能保证长方体的唯一性,因此程序会一直挂掉
换抵挡装置(Kickdown)
点击查看代码
#include<stdio.h>
#include<string.h>
int n1[105], n2[105];
char s1[105], s2[105];
int main()
{
while(scanf("%s", s1) == 1)
{
int len1, len2, flag = 0;
scanf("%s", s2);
if((len1 = strlen(s1)) >= (len2 = strlen(s2)))
{
for(int i = 0; i < len1; i++)
n1[i] = s1[i] - '0';
for(int i = 0; i < len2; i++)
n2[i] = s2[i] - '0';
}
else
{
len1 = strlen(s2);
len2 = strlen(s1);
for(int i = 0; i < len1; i++)
n1[i] = s2[i] - '0';
for(int i = 0; i < len2; i++)
n2[i] = s1[i] - '0';
}
int left = len1 - len2 + 1;
for(int i = 0; i < left; i++)
{
for(int k = 0; k < len2; k++)
{
if(n1[i + k] + n2[k] > 3)
break;
else if(n1[i + k] + n2[k] <= 3 && k == len2-1)
{
printf("%d\n", len1);
flag = 1;
}
}
if(flag)
break;
}
if(flag)
continue;
for(int i = 1; i < len2; i++)
{
for(int k = 0; k < len2 - i; k++)
{
if(n2[i + k] + n1[k] > 3)
break;
else if(n2[i + k] + n1[k] <= 3 && k == len2 - i -1)
{
printf("%d\n", len1+i);
flag = 1;
break;
}
}
if(flag)
break;
for(int k = 0; k < len2 - i; k++)
{
if(n2[k] + n1[len1 - len2 + i + k] > 3)
break;
else if(n2[k] + n1[len1 - len2 + i + k] <= 3 && k == len2 - i - 1)
{
printf("%d\n", len1 + i);
flag = 1;
break;
}
}
if(flag)
break;
}
if(!flag)
printf("%d\n", len1 + len2);
}
return 0;
}
注意:本题的装置是不可以翻转或旋转的,即只能按照题目所给的顺序来进行判断
浮点数(Floating-Point Numbers)
点击查看代码
#include<stdio.h>
#include<math.h>
#include<string.h>
#define min 1e-4
double ans[11][31];
char s[25];
int main()
{
for(int i = 0; i < 10; i++)
{
for(int j = 1; j < 31; j++)
{
ans[i][j] = log10(1-pow(2, -(i+1))) + (pow(2, j) - 1) * log10(2);
}
}
while(scanf("%s", s))
{
if(s[0] == '0' && s[1] == 'e' && s[2] == '0')
break;
double a = s[0] - '0';
int b = 0, flag = 1;
for(int i = 2; i < strlen(s); i++)
{
if(flag)
{
if(s[i] != 'e')
a += (s[i] - '0') * pow(10, -i+1);
else
flag = 0;
}
else
{
b *= 10;
b += s[i] - '0';
}
}
for(int i = 0; i < 10; i++)
{
for(int j = 1; j < 31; j++)
{
if((log10(a) + b) > ans[i][j])
{
if((log10(a) + b) - ans[i][j] < min)
{
printf("%d %d\n", i, j);
flag = 1;
break;
}
}
else
if(ans[i][j] - (log10(a) + b) < min)
{
printf("%d %d\n", i, j);
flag = 1;
break;
}
}
if(flag)
break;
}
}
return 0;
}
/*
1.C语言中的log函数有两种,一种是log10以10为底,一种是log以e为底
2.C语言中的pow函数是幂函数,pow(x,y),就是x的y次方的意思
*/
注意:本题的难度偏向于数学题,也就是说正常的模拟思路不适合本题,通过正常的方法模拟,模拟现实会造成很大的浪费,而这时候需要我们对于原先的数据进行一些整理,oi这边非常喜欢取对数,下次做题的时候可以多往这边想,同时对于初级模拟难以实现的问题,需要考虑对于问题的再加工,当然这边也引入了新的函数,本程序也有缺陷,读取数据实在过于笨重,等以后学成归来再来修改吧。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)