善用常量数组可以简化代码
同样利用了常量数组来存储镜像字符
for (int i = 1; i <=9; i++)
{
int c1 = 0, c2 = 0;
for (int j = 0; j < n; j++)
{
if (a[j] == i)
c1++;
if (b[j] == i)
c2++;
}
B += c1 > c2 ? c2 : c1;
}
//至于为什么是减去最小的个数,是因为题意要求
//现在的B是还带有位置正确的B
//因此输出时要减去A
我的基本思路:
从1到n,将每一个i用sprintf()输入到一个字符串,然后每一位对应一个字符。
因此求出每一个i+i的各位,与n比较。
如果相等,则最小值就是 i (因为是从小到大),这样直接跳出
如果不等,继续。
#include
#include
int main()
{
int n;
scanf("%d", &n);
char buf[10];
for (int i = 1; i < n; i++)
{
int n1 = i;
sprintf(buf, "%d", i);
int len = strlen(buf);
for (int j = 0; j < len; j++)
{
n1 += buf[j] - '0';
}
if (n == n1)
{
printf("%d", i);
break;
}
}
return 0;
}
刘:
我的方法效率不高,因为每次计算一个n都要枚举n-1个数。
因此,更快的做法是:
只需一次性枚举10000内所有正整数m,标记“m加上m的各个数字之和得到的数有一个生成元是m”,最后查表即可。
#include
#include
#define maxn 10005
int ans[maxn];
int main()
{
int T, n;
memset(ans, 0, sizeof(ans));
for (int m = 1; m < maxn; m++) //制表
{
int x = m, y = m;
while (x > 0)
{
y += x % 10;
x /= 10;
} //计算每一个生成元m对应的值是
if (ans[y] == 0 || m < ans[y]) //"||"是为了存储最小的生成元
ans[y] = m;
}
scanf("%d", &T);
while (T--)
{
scanf("%d", &n);
printf("%d\n", ans[n]);
}
return 0;
}
字典序:字符串在字典中的顺序。
一般地,对于两个字符串,从第一个字符开始比较,当某一个位置的字符不同时,该位置字符较小的串,字典序较小;
如果其中一个字符串已经没有更多的元素了,但另一个字符串还没有结束,则较短的字符串的字典序较小。
刘的代码:
#include
#include
#define maxn 105
int less(const char* s, int p, int q)
{
int n = strlen(s);
for (int i = 0; i < n; i++)
{
if (s[(p + i) % n] != s[(q + 1) % n]) //%是为了循环
return s[(p + i) % n] < s[(q + i) % n]; //如果有不相等的,返回比较结果
}
return 0;
}
int main()
{
int T;
char s[maxn];
scanf("%d", &T);
while (T--)
{
scanf("%s", s);
int ans = 0;
int n = strlen(s);
for (int i = 1; i < n; i++) //从1到n-1与从0开始的比较,找出最小的字符串
{
if (less(s, i, ans)) //如果从i开始的序列比从ans开始的要小,则把最小的ans重新赋值,即将i赋给ans
ans = i;
}
for (int i = 0; i < n; i++) //循环输出,想想循环队列的实现效果
{
putchar(s[(i + ans) % n]);
}
putchar('\n');
}
return 0;
}
总结:
循环字符串的方式,也就是循环队列的思想方法。
数组的循环,就是(i+index)%n。循环的实现,很有用
提醒:
每当用到a[i]或s[i]这样的元素时,应该问自己:“ i ”等于多少?它有什么实际的含义?作为数组下标,i 经常代表“当前考虑的位置”,或者与另一个下标 j 一起表示“当前考虑的子串的起点和终点”
对于中文的GBK编码:如果char值为正,则是西文字符;如果char为负,则是汉字的前一半(这时需要再读入一个char)
数组的大小可以用sizeof在编译时获得(它不是一个函数),它经常被用在memset,memcpy等函数中。
如果按照自己的方式处理字符串,千万要保证它以’\0’结尾
习题3-1 UVa1585
//这个题没有什么难的
//应该算是简单的模拟题,它让你做啥,你就做啥就可以了。
#include
#include
char seq[85];
int a[85];
int main()
{
int T;
scanf("%d", &T);
for (int i = 1; i <= T; i++)
{
memset(a, 0, sizeof(a));
scanf("%s", seq);
int len = strlen(seq);
for (int i = 0; i < len; i++)
{
if (seq[i] == 'X')
a[i] = 0;
else if (seq[i] == 'O')
a[i] = a[i - 1] + 1;
}
int sum = 0;
for (int i = 0; i < len; i++)
{
sum += a[i];
}
printf("%d\n", sum);
}
return 0;
}
习题3-2 UVa1586
//也没有什么就是模拟题
//不过处理字符串的地方还要注意再注意
//这个对于字母后面没有数字时,处理方式有点意思。
//也就这点了
#include
#include
#include
int main()
{
int T;
scanf("%d", &T);
char op[85];
for (int i = 1; i <= T; i++)
{
double sum = 0;
scanf("%s", op);
int len = strlen(op);
for (int i = 0; i < len;)
{
if (isalpha(op[i]))
{
int k = 0;
int j = i;
while (isdigit(op[++j]))
{
k = k * 10 + op[j] - '0';
}
if (k == 0)
k = 1;
if (op[i] == 'C')
{
sum += 12.01 * k;
}
else if (op[i] == 'H')
{
sum += 1.008 * k;
}
else if (op[i] == 'O')
{
sum += 16.00 * k;
}
else if (op[i]=='N')
{
sum += 14.01 * k;
}
i = j;
}
}
printf("%.3lf\n", sum);
}
return 0;
}
习题3-3 UVa1225
//这个也不难
#include
#include
int main()
{
int n;
int num;
int a[10];
scanf("%d", &n);
for (int i = 1; i <= n; i++)
{
memset(a, 0, sizeof(a));
scanf("%d", &num);
for (int i = 1; i <= num; i++)
{
int j = i;
while (j != 0)
{
a[j % 10]++;
j /= 10;
}
}
for(int i=0;i<10;i++)
{
if (i == 0)
printf("%d", a[i]);
else
printf(" %d", a[i]);
}
printf("\n");
}
return 0;
}
习题3-4 UVa455
//周期串,那么总长度%周期子串的长度,起码得是个0
#include
#include
int main()
{
int n;
int j;
char s[85];
scanf("%d", &n);
for (int i = 1; i <= n; i++)
{
scanf("%s", s);
int len = strlen(s);
for (int i = 1; i <= len; i++)
{
if (len % i == 0) //注意这里,既然是周期串,那么周期子串的长度%总长度是为0才可以
{ //如果缺少了这一句,会导致错误,比如说dhasjdh;虽然当i=5时,d=d,h=h,这两句相等了,然后j就大于7跳出了,这是错的
for (j = i; j < len; j++)
{
if (s[j] != s[j % i])
break;
}
if (j >= len)
{
printf("%d\n", i);
break;
}
}
else continue;
}
if (i != n)
printf("\n");
}
return 0;
}
习题3-5 UVa227
#include
#include
char map[5][5];
int main()
{
int end = 0;
int count = 0;
while (1)
{
int x, y;
int error = 0;
memset(map, ' ', sizeof(map));
for (int i = 0; i < 5; i++)
{
for (int j = 0; j < 5; j++)
{
map[i][j] = getchar();
//if (j == 4 && map[i][j] == '\n') //貌似是因为复制粘贴的缘故,导致如果空格在一行的最后,它会读取不到,因此加一个判断.
//map[i][j] = ' ';
//这个地方果然是因为复制粘贴问题。可以去掉
if (map[i][j] == '\n') //这是判断如果读到回车,就继续读,把回车舍掉
map[i][j] = getchar();
if (map[i][j] == ' ')
{
x = i;
y = j;
}
if (map[i][j] == 'Z')
{
end = 1;
break;
}
}
if (end == 1)
break;
if (i == 0 && count != 0)
printf("\n");
}
if (end == 1)
break;
char move;
while ((move = getchar()) != EOF && move != '0')
{
while (move == '\n')
move = getchar();
if (move == '0') //这个地方,简直灭绝人性
break;
switch (move)
{
case 'A':
if (x != 0)
{
map[x][y] = map[x - 1][y];
map[x - 1][y] = ' ';
x = x - 1;
}
else
{
error = 1;
}
break;
case 'B':
if (x != 4)
{
map[x][y] = map[x + 1][y];
map[x + 1][y] = ' ';
x = x + 1;
}
else
{
error = 1;
}
break;
case 'R':
if (y != 4)
{
map[x][y] = map[x][y + 1];
map[x][y + 1] = ' ';
y = y + 1;
}
else
{
error = 1;
}
break;
case 'L':
if (y != 0)
{
map[x][y] = map[x][y - 1];
map[x][y - 1] = ' ';
y = y - 1;
}
else
{
error = 1;
}
break;
default:
error = 1;
break;
}
}
printf("Puzzle #%d:\n", ++count);
if (error != 1)
for (int i = 0; i < 5; i++)
{
for (int j = 0; j < 5; j++)
{
putchar(map[i][j]);
if (j != 4)putchar(' ');
}
putchar('\n');
}
else printf("This puzzle has no final configuration.\n");
}
return 0;
}
习题3-6 UVa232
习题3-7 UVa1368
习题3-8 UVa202
习题3-9 UVa10340
习题3-10 UVa1587
习题3-11 UVa1588
习题3-12 UVa11809