3-1 开灯问题
有n盏灯,编号为1~n。第一个人把所有打开,第2个人按下所有编号为2的倍数的开关(这些灯将被关掉),第3个人按下所有编号为3的倍数的开关 (其中关掉的灯被打开你,开着的灯将被关闭),一次类推。一共有k个人,问最后又哪些灯开着?输入 :n和k,输出开着的灯编号。k <= n <= 1000.
样例输入:7 3
样例输出:1 5 6 7
Code#include<stdio.h> #include<string.h> const int maxn = 1000 + 5; int main() { int n, k, light[maxn], t = -1; while(scanf("%d%d", &n, &k) == 2) { t = -1; memset(light, -1, sizeof(light)); //初始状态都是关着的(1表示开,-1表示关) for(int i = 1; i <= k; ++i) for(int j = i; j <= n; j += i) light[j] *= t; for(int i = 1; i <= n; ++i) if(light[i] == 1) printf("%d ", i); printf("\n"); } return 0; }
3-2 蛇形填数(抽象问题)
在n*n方阵里填入1,2,…,n*n,要求填成蛇形。例如4时方阵为:
10 11 12 1
9 16 13 2
8 15 14 3
7 6 5 4上面的方阵中,多余的空格只是为了便于观察规律,不必严格输出。n <= 8。
从x=0,y=n-1,即第0行,第n-1列。“笔”的移动轨迹是:下,下,下,,左,左,左,上,上,上,右,右,下,下,上。总之,先是下,都不能填了为止,然后是左,接着是上,最后是右。“不能填”是指再走就出界了,或者再走就要走到以前体拿过的格子。如果我们把所有格子初始化为0,就能方百年地加以判断。
C++_Style:Code1#include<stdio.h> #include<string.h> const int maxn = 5000+10; int snag[maxn][maxn]; int main() { int n, x, y; while(scanf("%d", &n) == 1) { memset(snag, 0, sizeof(snag)); //设置标志以方便判断数组是否已经赋值 int num = snag[x=0][y=n-1]= 1; while(num < n*n) { //抽象为下、左、上、右四个方向的移动, while(x+1 < n && !snag[x+1][y]) snag[++x][y] = ++num; while(y-1 >= 0 && !snag[x][y-1]) snag[x][--y] = ++num; while(x-1 >= 0 && !snag[x-1][y]) snag[--x][y] = ++num; while(y+1 < n && !snag[x][y+1]) snag[x][++y] = ++num; } for(x = 0; x < n; ++x) { for(y = 0; y < n; ++y) printf("%3d ", snag[x][y]); printf("\n"); } } return 0; }
Code2#include<iostream> #include<cstring> using namespace std; const int maxn = 5000 + 10; int a[maxn][maxn];//(当数组很大时)数组必须开到外面 int main() { int n; while(cin >> n) { int x, y, cnt; memset(a, 0, sizeof(a)); cnt = a[x=0][y=n-1] = 1; while(cnt < n*n) { while(x+1 < n && !a[x+1][y]) a[++x][y] = ++cnt; while(y-1 >= 0 && !a[x][y-1]) a[x][--y] = ++cnt; while(x-1 >= 0 && !a[x-1][y]) a[--x][y] = ++cnt; while(y+1 < n && !a[x][y+1]) a[x][++y] = ++cnt; } for(x = 0; x < n; ++x) { for(y=0; y < n; ++y) { cout.width(5); cout.setf(ios::right); cout << a[x][y] << " "; } cout << endl; } } return 0; }
3-3 竖式问题
找出所有形如abc*de(三位数乘以两位数)的算式,使得在完整的竖式中,所有数字都属于一个特定的集合。输入数字集合(相邻数字之间没有空格),输出所有竖式。每个竖式前对应有编号,只有应有一个空行。最后输出解的总数。
样例输入:2357
样例输出:
<1>
775
X 33
-----
2325
2325
-----
25575
The number of solutions = 1
Code#include<stdio.h> #include<string.h> int main() { int i, ok, abc, de, x, y, z, count; char s[20], buf[99]; //printf("%c\n", 999);?的ASCII码是999. while(scanf("%s", s) == 1) { count = 0; for(abc = 111; abc <= 999; abc++) for(de = 11; de <= 99; de++) { x = abc*(de%10); //x存储与各位相乘的结果 y = abc*(de/10); //y存储与市十位相乘的结果 z = abc*de; //z存储最终结果 sprintf(buf, "%d%d%d%d%d", abc, de, x, y, z); ok = 1; for(i = 0; i < strlen(buf); i++) if(strchr(s, buf[i]) == NULL)//如果在s中buf[i]不存在,ok置0 ok = 0; if(ok) { printf("<%d>\n", ++count); printf("%5d\nX%4d\n-----\n%5d\n%4d\n-----\n%5d\n\n", abc, de, x, y, z); } } printf("The number of solutions = %d\n", count); } return 0; }
3-4 回文串(编码阶段可以采用迭代式开发:每次只实现一点小功能,但要充分测试,确保它工作正常。)
输入一个字符串,求出其中最长的回文子串。字串的含义是:在原串中连续出现的字符串片段。回文的含义是:正着看和倒着看相同,如abba和yyxyy。在判断时,应该忽略suoyou8标点符号和空格,且忽略大小写,单输出应保持鸳鸯(在回文串的首部和尾部不要输出多余字符)。输入字符串长度不超过5000,且占据单独一行。应该输出最长的回文串,如果有多个,输出起始位置最靠左的。
样例输入:Cofuciuss say:Madam,i'm Adam.
样例输出:Madam, i'm Adam
Code#include<stdio.h> #include<string.h> #include<ctype.h> const int maxn = 5000+10; char buf[maxn], str[maxn]; int sub[maxn]; int main() { while(fgets(buf, maxn, stdin)) { int len = strlen(buf), cnt = 0; for(int i = 0; i < len; ++i) if(isalpha(buf[i])) { sub[cnt] = i; //存入下标 str[cnt++] = toupper(buf[i]); } int max = 0, beg, end; for(int i = 0; i < cnt; ++i) { for(int j = 0; i-j >= 0 && i+j < cnt; ++j) { //偶数个 if(str[i-j] != str[i+j]) break; if(2*j+1 > max) { max = 2*j + 1; beg = sub[i-j]; end = sub[i+j]; } } for(int j = 0; i-j >= 0 && i+j+1 < cnt; ++j) { //奇数个 if(str[i-j] != str[i+j+1]) break; if(2*j+2 > max) { max = 2*j + 2; beg = sub[i-j]; end = sub[i+j+1]; } } } for(int i = beg; i <= end; ++i) putchar(buf[i]); putchar('\n'); } return 0; } /*
转载于:https://www.cnblogs.com/sanghai/archive/2012/12/19/2825639.html