算法竞赛入门经典(第2版)第3章
开灯问题
开灯问题,有n盏灯,编号为1~n。第一个人把所有灯都打开,第二个人按下所有编号为2的倍数的开关(这些灯将被关掉),第三个人按下所有编号为3的倍数的开关(其中关掉的灯将被打开,开着的灯将被关闭),以此类推。一共有k个人,问最后有哪些灯开着?输入n和k,输出开着的灯的编号。k<=n<=1000。
样例输入:
7 3
样例输出:
1 5 6 7
【分析】
用a[1],a[2],··· ,a[n]表示编号为1,2,3,··· ,n的灯是否开着。模拟这些操作即可。
#include<iostream>
int main()
{
int n, k, first = 1;
int a[10]{};
std::cin >> n >> k;
for (int i = 1; i <= k; i++)
for (int j = 1; j <= n; j++)
if (j % i == 0) a[j] = !a[j];
for (int i = 1; i <= n; i++)
if (a[i])
{
if (first)
first = 0;
else
std::cout << " ";
std::cout << i;
}
return 0;
}
竖式问题
找出所有形如abc*de(三位数乘以两位数)的算式,使得在完整的竖式中,所有数字都属于一个特定的数字集合。输入数字集合(相邻数字之间没有空格),输出所有竖式。每个竖式前应有编号,之后应有一个空行。最后输出解的总数。具体格式见样例输出(为了便于观察,竖式中的空格改用小数点显示,但你的程序应该输出空格,而非小数点)。
样例输入:2357
样例输出:
<1>
…775
X…33
.2325
2325.
25575
The number of solutions = 1
#include<stdio.h>
#include<string.h>
int main(void)
{
char s[20], buff[99];
int count = 0;
scanf("%s", s);
for (int abc = 101; abc <= 999; abc++)
{
for (int de = 11; de <= 99; de++)
{
int x = abc * (de % 10);
int y = abc * (de / 10);
int ok = 1;
sprintf(buff, "%d%d%d%d%d", abc, de, x, y, abc * de);
for (int i = 0; i < strlen(buff); i++)
if (strchr(s, buff[i]) == NULL)
ok = 0;
if (ok)
{
printf("<%d>\n", ++count);
printf("%5d\n", abc);
printf("X%4d\n", de);
printf("-----\n");
printf("%5d\n", x);
printf("%5d\n", y);
printf("-----\n");
printf("%5d", abc * de);
}
}
}
printf("The number of solutions = %d\n", count);
return 0;
}
Tex 中的引号(Tex Quotes,Uva 272)
在Tex中,左双引号是“``”,右双引号是"’’"。输入一篇包含双引号的文章,你的任务是把它转换成TeX的格式。
样例输入:
"To be or not to be," quoth the Bard,"that is the question".
样例输出:
``To be or not to be,'' quoth the Bard,``that is the question''
#include<stdio.h>
int main()
{
int c, q = 1;
while ((c = getchar()) != EOF)
{
if (c == '"')
{
printf("%s", q ? "``" : "''");
q = !q;
}
else
printf("%c", c);
}
return 0;
}
WERTYU (WERTYU, UVa10082)
WERTYU 把手放在键盘上,稍不注意就会往右错一位。这样,输入Q会变成输入W,输入J会变成输入K等。
输入一个错位后敲出的字符串(所有字母均大写),输出打字员本来想打出的句子。
输入保证合法,即一定是错位之后的字符串。例如输入中不会出现大写字母A.
样例输入;
O S, GOMR YPFSU/
样例输出:
I AM FINE TODAY.
#include<stdio.h>
char s[] = "`1234567890-=QWERTYUIOP[]\ ASDFGHJKL;'ZXCVBNM,./";
int main()
{
int i, c;
while ((c = getchar()) != EOF)
{
for (i = 0; s[i] && s[i] != c; i++);
if (s[i]) putchar(s[i-1]);
else putchar(c);
}
return 0;
}
回文词(PAlindromes, UVa401)
输入一个字符串,判断它是否为回文以及镜像串。输入字符串保证不含数字0.所谓回文串,就是反转之后原串相同,如abba和madam。所谓镜像串,就是左右镜像之后和原串相同,如2S和3AIAE。注意,并不是每个字符在镜像之后都能得到一个合法字符,本题中,每个字符的镜像如下所示,(空白项表示该字符镜像后不能得到一个合法的字符)。
输入的每行包含一个字符串(保证只有上述字符。不含空白字符),判断它是否为回文 串和镜像串(共4种组合)。每组数据之后输出一个空行。
样例输入:
NOTAPALINDROME
ISAPALINILAPASI
2A3MEAS
ATOYOTA
样例输出:
NOTAPALINDROME – is not a palindrome.
ISAPALINILAPASI – is a regular palindrome.
2A3MEAS – is a mirrored string.
ATOYEOTA – is a mirrored palindrome.
#include<stdio.h>
#include<string.h>
#include<ctype.h>
const char * rev = "A 3 HIL JM O 2TUVWXY51SE Z 8";
const char * msg[] = {"not a palindrome", "a regular palindrome", "a mirrored string", "a mirrored palindrome"};
char r(char ch)
{
if (isalpha(ch)) return rev[ch - 'A'];
return rev[ch - '0' + 25];
}
int main()
{
char s[30];
while (scanf("%s", s) == 1)
{
int len = strlen(s);
int p = 1, m = 1;
for (int i = 0; i < (len + 1) / 2; i++ )
{
if (s[i] != s[len - 1 - i]) p = 0;
if (r(s[i]) != s[len - 1 - i]) m = 0;
}
printf("%s -- is %s.\n\n", s, msg[m*2+p]);
}
return 0;
}
