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这边非常喜欢取对数,下次做题的时候可以多往这边想,同时对于初级模拟难以实现的问题,需要考虑对于问题的再加工,当然这边也引入了新的函数,本程序也有缺陷,读取数据实在过于笨重,等以后学成归来再来修改吧。

posted @   banyanrong  阅读(40)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)
点击右上角即可分享
微信分享提示