2021.09.29 10:35:44
更新:这么翻着看太麻烦了,做了个小工具,这里就先不更新了。
听说XDOJ上的题有200多道,刷的题在这记下,以后备用。
过于简单的就直接放代码了。
不知道哪找的题,题解写这了
给定一个整数数列,数列中连续相同的最长整数序列算成一段,问数列中共有多少段?
输入的第一行包含一个整数n,表示数列中整数的个数。
第二行包含n个整数a1, a2, …, an,表示给定的数列,相邻的整数之间用一个空格分隔。
输出一个整数,表示给定的数列有多个段。
8
8 8 8 0 12 12 8 0
5
/* array_count.c - by xeonds - 2021.10.15 23:00 */
#include <stdio.h>
int main(void)
{
int i,j,num_curr,num_prev,count;
("%d",&i);
scanffor(j=0,count=1;j<i;j++)
{
if(j==0)
{
("%d",&num_prev);
scanfcontinue;
}
("%d",&num_curr);
scanfif(num_curr!=num_prev)
++;
count=num_curr;
num_prev}
("%d",count);
printf
return 0;
}
没来得及提交,不知道能不能过( 反正本地gcc运行是没问题的。但是OJ平台好像是VC6(叹 更新:已经找到题了,过了( —
第一次上机的练习题。大多数都很简单,除了一个隐式转换的坑。
#include <stdio.h>
int main(void)
{
int a,b,c;
("%d %d %d",&a,&b,&c);
scanf("%d",a+b+c);
printf
return 0;
}
/* calc triangle area - by xeonds */
#include <stdio.h>
#include <math.h>
int main(void)
{
float a,b,c,p;
("%f %f %f",&a,&b,&c);
scanf=(a+b+c)/2;
p("%.2f",sqrt(p*(p-a)*(p-b)*(p-c)));
printf
return 0;
}
#include <stdio.h>
int main(void)
{
int a,b;
("%d %d",&a, &b);
scanf("%d\n%d\n%d\n%d\n",a+b,a-b,a*b,a/b);
printf
return 0;
}
这里注意下,字母大小写转换可以用ascii码的方式进行,也可以用二进制格式按位操作的方式完成。
#include <stdio.h>
int main(void)
{
int ch;
for(int i=0;i<9;i++)
{
=getchar();
chif(i%2==0)
(ch+32);
putchar}
("!");
printf
return 0;
}
注意,转换说明要和数据类型匹配。
#include <stdio.h>
int main(void)
{
float a,b,c;
("%f %f %f",&a,&b,&c);
scanf("%.3f",a*b*c);
printf
return 0;
}
这里不能用减的原因是,减有可能会产生负数,这在ascii码体系中是未定义的。
/* int add char - by xeonds */
#include <stdio.h>
int main(void)
{
int a,ch;
("%d,%d",&a,&ch);
scanf("%d,%d",a+ch+48,a+ch);
printf
return 0;
}
#include <stdio.h>
#define PI 3.1415926
#define FE 7.86
#define AG 19.3
float mass(int a,float p);
int main(void)
{
int d_1,d_2;
("%d %d",&d_1,&d_2);
scanf("%.3f %.3f",mass(d_1,FE),mass(d_2,AG));
printf
return 0;
}
float mass(int a, float p)
{
float m;
= 4*PI*a*a*a*p/3/1000/8;
m
return m;
}
#include <stdio.h>
int main(void)
{
int a,b;
("%d %d",&a,&b);
scanfif(a%b==0)
("yes");
printfelse
("%d %d",a/b,a%b);
printf
return 0;
}
本来是想写得更通用一些,但是任务太简单,没必要。
#include <stdio.h>
int main(void)
{
int i;
("%d",&i);
scanf("%d",i%10+(i%100-i%10)/10+(i-i%100)/100);
printf
return 0;
}
更通用一点的算法:任意位(不超过int范围)各位求和:
/* calc_bit_sum.c -by xeonds - 2021.10.16 15:11 */
#include <stdio.h>
int calc(int num);
int main(void)
{
int num;
("%d", &num);
scanf("%d", calc(num));
printf
return 0;
}
int calc(int num)
{
if (num >= 10)
return num % 10 + calc((num - num % 10) / 10);
else
return num;
}
这有个坑,好多人都掉进来了:数据的隐式转换。赋值表达式右值的数据类型会自动转换成其中容纳范围最大的项的数据类型。
比如,c=1+3/2
的结果是2,而c=1+3/2.0
的结果是2.50
。
/* temperature convert - by xeonds */
#include <stdio.h>
float f_to_c(int a);
int main(void)
{
int f;
("%d",&f);
scanf("%.2f",f_to_c(f));
printf
return 0;
}
float f_to_c(int a)
{
float c;
= (a-32.00)*5.00/9.00;
c
return c;
}
第二次上机练习的题,都很简单。注意下文档编码问题,包含中文的最好用GB2312编码
输入二元表达式,进行运算。初中写过一个计算器,比这个复杂些。
#include <stdio.h>
int calc(int a, int b, char calc);
int main(void)
{
int num_1, num_2;
char ch;
("%d%c%d", &num_1, &ch, &num_2);
scanf("%d%c%d=%d", num_1, ch, num_2, calc(num_1, num_2, ch));
printf
return 0;
}
int calc(int a, int b, char calc)
{
switch (calc)
{
case '+':
return a + b;
case '-':
return a - b;
case '*':
return a * b;
case '/':
return a / b;
case '%':
return a % b;
}
}
注意,C语言中整数的除法结果都是带余除法,取余运算是%
,是二元运算符,只接受整数作为运算对象。
输出数字的各位。相当于给各位间加了个空格。这里用的是数学办法。
#include <stdio.h>
int main(void)
{
int a, i;
("%d", &a);
scanffor (i = 1; a >= i; i *= 10)
;
/= 10;
i for (; a > 0;)
{
("%d ", a / i);
printf-= a / i * i;
a /= 10;
i }
return 0;
}
注意空语句。它只有一个符号;
,但是是一个完整的语句。
很简单。注意将数据类型隐式转换为浮点数即可。
/* 2.3 温度计算 - by xeonds */
#include <stdio.h>
int main(void)
{
int h, m;
("%d %d", &h, &m);
scanf("%.2f\n", 4.0 * (h + m / 60.0) * (h + m / 60.0) / ((h + m / 60.0) + 2) - 20);
printf
return 0;
}
怎么又是小明((╯‵□′)╯︵┻━┻)
#include <stdio.h>
int main(void)
{
int m, n, q, r;
("%d %d %d %d", &m, &n, &q, &r);
scanfif (m / n == q && m % n == r)
("yes");
printfelse
("%d %d", m / n, m % n);
printf
return 0;
}
#include <stdio.h>
int main(void)
{
("C programming language is useful!");
puts("I like it very much.");
puts
return 0;
}
注意隐式转换。
#include <stdio.h>
int main(void)
{
int a, b, c;
("%d %d %d", &a, &b, &c);
scanf("%.2f", (a + b + c) / 3.0);
printf
return 0;
}
#include <stdio.h>
int main(void)
{
float r;
("%f", &r);
scanf("%.2f", 4 * 3.14 * r * r * r / 3);
printf
return 0;
}
下面的程序可以抽象成函数来简化。
待会写(咕
#include <stdio.h>
int main(void)
{
int salary, m100 = 0, m50 = 0, m20 = 0, m10 = 0, m5 = 0, m1 = 0;
("%d", &salary);
scanfif (salary >= 100)
= salary / 100, salary = salary % 100;
m100 if (salary >= 50)
= salary / 50, salary = salary % 50;
m50 if (salary >= 20)
= salary / 20, salary = salary % 20;
m20 if (salary >= 10)
= salary / 10, salary = salary % 10;
m10 if (salary >= 5)
= salary / 5, salary = salary % 5;
m5 if (salary >= 1)
= salary / 1;
m1 ("%d %d %d %d %d %d", m100, m50, m20, m10, m5, m1);
printf
return 0;
}
写出来之后感觉完全没有简化(笑)
#include <stdio.h>
#include <stdlib.h>
int *m_calc(int m_size, int salary);
int main(void)
{
int salary;
("%d", &salary);
scanf("%d %d %d %d %d %d", m_calc(100, salary)[0],
printf(50, m_calc(100, salary)[1])[0],
m_calc(20, m_calc(50, m_calc(100, salary)[1])[1])[0],
m_calc(10, m_calc(20, m_calc(50, m_calc(100, salary)[1])[1])[1])[0],
m_calc(5, m_calc(10, m_calc(20, m_calc(50, m_calc(100, salary)[1])[1])[1])[1])[0],
m_calc(1, m_calc(5, m_calc(10, m_calc(20, m_calc(50, m_calc(100, salary)[1])[1])[1])[1])[1])[0]);
m_calc
return 0;
}
int *m_calc(int m_size, int salary)
{
int *res;
= (int *)malloc(sizeof(int) * 2);
res [0] = salary / m_size; //number of money
res[1] = salary % m_size; //rest of salary
resreturn res;
}
#include <stdio.h>
int main(void)
{
int a, b, c;
("%d %d %d", &a, &b, &c);
scanfif (a + b > c && a + c > b && b + c > a)
("%d", a + b + c);
printfelse
("No");
printf
return 0;
}
判断部分可以用三目运算符简化成这样:
(a + b > c && a + c > b && b + c > a)?printf("%d", a + b + c):printf("No");
utf-8大法好,gb2312太谔谔了(ψ(`^´)ψ
//encoding: GB2312
#include <stdio.h>
int main(void)
{
int a;
("%d", &a);
scanfif (a > 0)
if (a % 2 == 1)
("奇数");
printfelse
("偶数");
printf
return 0;
}
#include <stdio.h>
int main(void)
{
int num;
("%d",&num);
scanfif(num%35==0)
("yes");
printfelse
("no");
printf
return 0;
}
注意四舍五入的技巧:
float num=5.4;
(int)(num+0.5); //四舍五入
#include <stdio.h>
float calc(float s,int t);
int main(void)
{
float s;
int t;
("%f %d",&s,&t);
scanf("%d",(int)(calc(s,t)+0.5));
printf
return 0;
}
float calc(float s,int t)
{
float res=0;
=t/5*2;
resif(s>10)
+=24+3*(s-10);
reselse if(s>3)
+=10+2*(s-3);
reselse if(s>0)
+=10;
res
return res;
}
#include <stdio.h>
int main(void)
{
float r,p=1;
int n;
("%f %d",&r,&n);
scanffor(;n>0;n--)
*=1+r;
p("%.2f",p);
printf
return 0;
}
纯粹拿来恶心人的(虽然确实有实际应用背景
#include <stdio.h>
#include <math.h>
int main(void)
{
float month=0,d,p,r;
("%f %f %f",&d,&p,&r);
scanf=log10((double)(p/(p-d*r)))/log10(1+(double)r);
month("%.2f",month);
printf
return 0;
}
正经解法:
#include <stdio.h>
int main(void)
{
int ch[5] = "China", i;
for (i = 0; i < 5; i++)
(ch[i] + 4);
putchar
return 0;
}
不正经解法(大家别学我):
#include <stdio.h>
int main(void)
{
("Glmre");
printf
return 0;
}
其实这就是crypto(密码学)中的凯撒密码。
#include <stdio.h>
int main(void)
{
int m,s;
float t;
("%d %d",&m,&s);
scanf=m+s/60.0;
tif(t>50)
("%.1f",20.0);
printfelse if(t>30)
("%.1f",30-(t-30)/2);
printfelse if(t>10)
("%.1f",50-(t-10));
printfelse if(t>=0)
("%.1f",100-5*t);
printf
return 0;
}
第三次上机的题(不过标的是2?)难度很简单,唯一的问题是我没睡醒 《关于我8:00-12:00上机,我11:30醒这件事》
这下我终于知道那个第一题是哪来的了(
还请跳到第一题(
为了保持序号数值和xdoj题数一样,此处序号就用1了
因为任意两个数都得作差,所以偷了个懒,用malloc
把输入存到一个数组里了。
其实malloc
完后,和数组的用法就差不多了。
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int i, j, res, a, *arr;
("%d", &a);
scanf= (int *)malloc(sizeof(int) * a);
arr for (i = 0; i < a; i++) {
("%d", &arr[i]);
scanf}
for (i = 0; i < a - 1; i++)
for (j = i + 1; j < a; j++)
if (i == 0 && j == 1)
= arr[i] - arr[j] < 0 ? arr[j] - arr[i] : arr[i] - arr[j];
res else {
if (res > (arr[i] - arr[j] < 0 ? arr[j] - arr[i] : arr[i] - arr[j]))
= (arr[i] - arr[j] < 0 ? arr[j] - arr[i] : arr[i] - arr[j]);
res }
("%d", res);
printf
return 0;
}
看到群里有人在if
里套了switch
。其实没必要,限行的号码都是很有规律的。
#include <stdio.h>
int main(void) {
int a, b, c;
("%d %d %d", &a, &b, &c);
scanfif (a > 5 || b < 200)
("%d no", c % 10);
printfelse if (b < 400)
if (c % 5 == a % 5)
("%d yes", c % 10);
printfelse
("%d no", c % 10);
printfelse if (b >= 400)
if (c % 2 == a % 2)
("%d yes", c % 10);
printfelse
("%d no", c % 10);
printf
return 0;
}
另外可别学我if
和else
不加括号,初学的话很容易弄不清else
是属于哪个else
的。对于这个,知道else
属于最近的if
就行。
这里有个switch
的小技巧:case
语句可以通过不加break
来合并。
#include <stdio.h>
int calc(int y, int m) {
switch (m) {
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
return 31;
case 4:
case 6:
case 9:
case 11:
return 30;
case 2:
return (y % 4 == 0 && y % 100 != 0) || y % 400 == 0 ? 29 : 28;
}
}
int main(void) {
int a, b;
("%d %d", &a, &b);
scanf("%d", calc(a, b));
printf
return 0;
}
正好就是上面写的通用方法(
请上翻到10的通用写法。
所以说嘛,多想一点总是没错的。
#include <stdio.h>
int gcd(int a, int b) {
int res = 0, i;
if (a > b) {
= a;
i = b;
a = i;
b }
if (a == 0)
return b;
for (i = 1; i <= a; i++)
if (a % i == 0 && b % i == 0)
= i;
res
return res;
}
int main(void) {
int a, b;
("%d %d", &a, &b);
scanfif (a >= 0 && b < 10000)
("%d", gcd(a, b));
printf
return 0;
}
本来是想用
=a,a=b,b=i; i
来做a和b值的交换的,但是平台上那个hmp编译器好像不支持逗号运算符?
还是我搞错编译器了呢?(笑)
#include <stdio.h>
int main(void) {
int a, i;
("%d", &a);
scanffor (i = 0; a != 1; i++)
if (a % 2 == 0)
/= 2;
a else
= (a *= 3) + 1;
a ("%d", i);
printf
return 0;
}
#include <stdio.h>
int main(void) {
int res[6] = {0, 0, 0, 0, 0, 0}, data, a, i, sum;
("%d", &a);
scanffor (i = 0, sum = 0; i < a; i++) {
("%d", &data);
scanfif (data > 300)
[5]++;
reselse if (data > 200)
[4]++;
reselse if (data > 150)
[3]++;
reselse if (data > 100)
[2]++;
reselse if (data > 50)
[1]++;
reselse if (data >= 0)
[0]++;
res+= data;
sum }
("%.2f\n", (float)sum / a);
printffor (i = 0; i < 6; i++)
("%d ", res[i]);
printf
return 0;
}
注意,是相邻两天波动的绝对值最大值,而不是所有天温度的最大值减去最小值。
这里的prev
和curr
表示上一个和当前的,是写链表的习惯。
#include <stdio.h>
#include <math.h>
int main(void) {
int curr, prev, res, a, i, tmp;
("%d", &a);
scanfif (a >= 2 && a <= 30) {
for (i = 0, res = 0; i < a; i++) {
if (i == 0) {
("%d", &prev);
scanfcontinue;
}
("%d", &curr);
scanfif (abs(curr - prev) > res)
= abs(curr - prev);
res = curr;
prev }
("%d", res);
printf}
return 0;
}
前面有个同学问到过这个。需要注意,==
的使用前提是两边的数据类型相同,所以可以这么写:
if (sqrt(a) - (int)sqrt(a) == 0)
; statement
而不能这么写:
if (sqrt(a) == (int)sqrt(a))
; statement
#include <stdio.h>
#include <math.h>
int main(void) {
int a;
("%d", &a);
scanfif (sqrt(a) - (int)sqrt(a) == 0)
("%d", (int)sqrt(a));
printfelse
("no");
printf
return 0;
}
做这题的时候又犯迷糊了。。其实只需要相邻两数依次比较就行。第一回做的时候直接来了个O(n!)
的比较,纯属没睡醒。
#include <stdio.h>
int calc(int num);
int main(void) {
int a, i, data, res;
("%d", &a);
scanffor (i = 0; i < a; i++) {
if (i == 0) {
("%d", &res);
scanfcontinue;
}
("%d", &data);
scanfif (calc(res) < calc(data))
= data;
res else if (calc(res) == calc(data))
= res > data ? res : data;
res }
("%d", res);
printf
return 0;
}
int calc(int num) {
if (num >= 10)
return num % 10 + calc((num - num % 10) / 10);
else
return num;
}
其实好多时候都没有用函数的必要,除了必须递归的算法。
大多数时候,我这么用,只是用了自己总结的模板而已:大多数题都是输入数,经过处理再输出数。
重复的部分我是懒得再敲一遍的。
#include <stdio.h>
int calc(int a, int i) {
return 2 * i - (a + 1);
}
int main(void) {
int a, i;
("%d", &a);
scanfif (a > 0 && a < 30)
for (i = 1; i < a + 1; i++)
("%d ", a * a + calc(a, i));
printf
return 0;
}
怎么说呢,难度简单,就是做的有些晕。
果然下次还是得睡好啊(叹)。
#include <stdio.h>
int main(void) {
int y, m, d, n, n0, i,
[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
arr_n[12] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
arr_o
("%d %d", &y, &n);
scanfif (y % 4 == 0 && y % 100 != 0 || y % 400 == 0) {
for (m = 1; m <= 12; m++) {
for (i = 0, n0 = 0; i < m; i++)
+= arr_o[i];
n0 if (n <= n0) {
for (i = 0, n0 = 0; i < m - 1; i++)
+= arr_o[i];
n0 = n - n0;
d break;
}
}
} else {
for (m = 1; m <= 12; m++) {
for (n0 = 0, i = 0; i < m; i++)
+= arr_n[i];
n0 if (n <= n0) {
for (n0 = 0, i = 0; i < m - 1; i++)
+= arr_n[i];
n0 = n - n0;
d break;
}
}
}
("%d %d", m, d);
printf
return 0;
}
有个坑:第一个值为2的话,如果没初始化flag=0
的话就会出错。
给未初始化的值自增肯定有问题啊。
#include <stdio.h>
int main(void) {
int a, res = 0, flag=0;
while (scanf("%d", &a) && a != 0)
if (a == 1) {
++;
res= 0;
flag } else if (a == 2) {
++;
flag+= 2 * flag;
res }
("%d", res);
printf
return 0;
}
md,搞了半天,原来是输入得用EOF
结束。我就说看错误列表里全是time
out,原来oj上输入的终止符是EOF
。刚开始用的'\n'
,难怪过不了。
#include <stdio.h>
int main(void)
{
char ch;
int res = 0;
while ((ch = getchar()) != EOF)
+= ch;
res ("%d\n", res % 256);
printf
return 0;
}
第四次上机题很简单,不用想,但是写起来挺费时间 待会再写分析
浪费时间。
#include <stdio.h>
int main(void) {
double a, res;
("%lf", &a);
scanfif (a > 210) {
= (a - 210) * 0.70 + 110;
res } else if (a > 110) {
= (a - 110) * 0.55 + 55;
res } else if (a >= 0) {
= a * 0.5;
res }
("%.2lf", res);
printf
return 0;
}
#include <stdio.h>
int is_ok_num(int num);
int main(void) {
int i, a, b;
("%d %d", &a, &b);
scanffor (i = a; i <= b; i++)
if (is_ok_num(i))
("%d\n", i);
printf
return 0;
}
int is_ok_num(int num) {
int i, add;
for (i = 1, add = 0; i < num; i++)
+= (num % i == 0 ? i : 0);
add
return num == add ? 1 : 0;
}
#include <stdio.h>
int main(void) {
int a, max, min, bit;
("%d", &a);
scanf= min = a % 10;
max = a == 0 ? 1 : 0;
bit while (a != 0) {
int c = a % 10;
= max >= c ? max : c;
max = min <= c ? min : c;
min = (a -= a % 10) / 10;
a ++;
bit}
("%d %d %d\n", bit, max, min);
printf
return 0;
}
#include <stdio.h>
int main(void) {
int a, i, curr, prev, next, count;
("%d", &a);
scanffor (i = 1, count = 0; i < a - 1; i++)
if (i == 1) {
("%d %d %d", &prev, &curr, &next);
scanfif ((curr - prev) * (next - curr) < 0)
++;
count= curr, curr = next;
prev } else {
("%d", &next);
scanfif ((curr - prev) * (next - curr) < 0)
++;
count= curr, curr = next;
prev }
("%d", count);
printf
return 0;
}
#include <stdio.h>
int main(void) {
int num, i;
for (i = 0; i < 4; i++)
if (i == 1) {
("%d", &num);
scanfcontinue;
} else {
int curr;
("%d", &curr);
scanf= curr > num ? curr : num;
num }
("%d", num);
printf
return 0;
}
#include <stdio.h>
int main(void) {
int ch;
= getchar();
ch if (ch >= 65 && ch <= 90)
(ch + 32);
putcharelse if (ch >= 97 && ch <= 122)
(ch - 32);
putcharelse
(ch);
putchar
return 0;
}
#include <stdio.h>
int main(void) {
int score;
("%d", &score);
scanfif (score >= 90 && score <= 100)
('A');
putcharelse if (score >= 80)
('B');
putcharelse if (score >= 70)
('C');
putcharelse if (score >= 60)
('D');
putcharelse if (score >= 0)
('E');
putchar
return 0;
}
#include <stdio.h>
int main(void) {
int num, a, b, c;
("%d", &num);
scanffor (a = 0; a <= 9; a++)
for (b = 0; b <= 9; b++)
for (c = 0; c <= 9; c++)
if ((a + c) * 100 + b * 20 + (a + c) == num)
("%d %d %d\n", a, b, c);
printf
return 0;
}
#include <stdio.h>
int main(void) {
int a[3], i, j, tmp;
("%d %d %d", &a[0], &a[1], &a[2]);
scanffor (i = 0; i < 2; i++)
for (j = i + 1; j < 3; j++)
if (a[i] > a[j])
= a[i], a[i] = a[j], a[j] = tmp;
tmp if (a[0] + a[1] > a[2] && a[0] + a[2] > a[1] && a[1] + a[2] > a[0])
if (a[0] * a[0] + a[1] * a[1] == a[2] * a[2])
("%d", a[0]*a[1]);
printfelse
("no");
printfelse
("no");
printf
return 0;
}
#include <stdio.h>
int main(void) {
int num;
double res;
("%d", &num);
scanfif (num > 3500) {
-= 3500;
num if (num > 35000)
= (num - 35000) * 0.7 + 26000 * 0.75 + 4500 * 0.8 + 3000 * 0.9 + 1500 * 0.97;
res else if (num > 9000)
= (num - 9000) * 0.75 + 4500 * 0.8 + 3000 * 0.9 + 1500 * 0.97;
res else if (num > 4500)
= (num - 4500) * 0.8 + 3000 * 0.9 + 1500 * 0.97;
res else if (num > 1500)
= (num - 1500) * 0.9 + 1500 * 0.97;
res else
= num * 0.97;
res += 3500;
res } else
= num;
res ("%d", (int)res);
printf
return 0;
}
#include <stdio.h>
int main(void) {
int a, i, num;
double res;
("%d", &a);
scanffor (i = 0, res = 0; i < a; i++) {
("%d", &num);
scanf+= 1 / (double)a * (double)num;
res }
("%.2lf", res);
printf
return 0;
}
第五次上机练习题
难度简单,随便做就行
服务器卡的让人没心情做。。
水仙花数指大于等于三位的数,如果各位的位数次幂的和等于自身,则称为水仙花数。
要求交一个函数。。就,稍微有点麻烦。本来想用函数中声明函数的奇淫技巧,但是这样就没意思了,所以还是算了。。
int function(int a, int b)
{
/* tmp :临时变量,用于交换a,b的值
i :计数变量,用于表示a到b(含a,b)之间的所有数
count :计数变量,用于存储水仙花数的个数
*/
int tmp, i, count;
/* 交换a,b的值来确保a<b */
> b ? tmp = a, a = b, b = tmp : 1;
a /* 循环,遍历含a,b的在a,b间的所有数 */
for (i = a, count = 0; i <= b; i++)
{
/* bit :存储数字i的位数
bit_sum :存储数字i的各位幂次和
i_cpy :i的复制,用来参与求i位数的计算,防止i的值改变,影响循环
j :循环变量,用来参与求i各位幂次和的运算
*/
int bit, bit_sum, i_cpy = i, j;
/* 计算i的位数,存储到变量bit中 */
for (bit = 1; i_cpy / (int)pow(10, bit) != 0; bit++)
;
/* 恢复i_cpy的值为i,以便于参与接下来求i各位幂次和的运算 */
= i;
i_cpy /* 计算i的各位幂次和 */
for (j = 0, bit_sum = 0; j < bit; j++)
+= (int)pow(i_cpy % 10, bit), i_cpy /= 10;
bit_sum /* 根据水仙花数的定义(大于等于三位,各位幂次和为其本身)判断i是否为水仙花数 */
if (i == bit_sum && bit > 2)
++;
count}
return count;
}
先吐槽下XDOJ上的歌德巴赫猜想(xswl
思路就是for
循环,逐组尝试。注意C语言的模块化思想,设计程序时从抽象到具体。
#include <stdio.h>
int is_prime(int num) {
int i, res;
for (i = 1, res = 1; i < num; i++)
if (num % i == 0 && i != 1)
= 0;
res
return res;
}
int main(void) {
int a, i, min, max;
("%d", &a);
scanffor (i = 2; i < a; i++)
if (is_prime(i) && is_prime(a - i)) {
("%d %d", i, a - i);
printfbreak;
}
return 0;
}
直接把上面写好的is_prime
拿过来,再写个fib
,就完成了。
#include <stdio.h>
int is_prime(int num) {
int i, res;
for (i = 1, res = 1; i < num; i++)
if (num % i == 0 && i != 1)
= 0;
res
return res;
}
int fib(int i) {
if (i > 2)
return fib(i - 1) + fib(i - 2);
else
return 1;
}
int main(void) {
int num;
("%d", &num);
scanfif (is_prime(fib(num)))
("yes");
printfelse
("%d", fib(num));
printf
return 0;
}
一个关于斐波那契数列的数列,对其求和。
思路很清晰,就是先用斐波那契数列表示出来这个数列,然后再进行逐项求和运算。
#include <stdio.h>
double fib(int i) {
if (i > 2)
return fib(i - 1) + fib(i - 2);
else
return 1.0;
}
int main(void) {
int i, n;
double res;
("%d", &n);
scanffor (i = 0, res = 0; i < n; i++)
+= fib(i + 3) / fib(i + 2);
res ("%.2f", res);
printf
return 0;
}
注意ASCII码
的灵活运用。还有就是ch=getchar()
的终止条件不要选错,不然就是死循环了。
#include <stdio.h>
int main(void)
{
int ch, a = 0, b = 0;
while ((ch = getchar()) != EOF && ch != '\n')
if (ch >= '0' && ch <= '9')
++;
aelse if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z'))
++;
b("%d,%d", b, a);
printf
return 0;
}
查找字母在字符串中的出现次数。把上面那个题删减一下就行。
#include <stdio.h>
int main(void) {
int ch, c = 0;
while ((ch = getchar()) != EOF && ch != '\n')
if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z'))
++;
c("%d", c);
printf
return 0;
}
隔一个输出。所以用一个计数器就行了。
#include <stdio.h>
int fun(char *ch) {
int i;
for (i = 0; *ch != '\0'; i++)
if (i % 2 == 0)
(*ch++);
putcharelse
++;
ch}
int main(void) {
char ch[100];
("%s", &ch);
scanf(ch);
fun
return 0;
}
不正经解法。别学我(
正经解法是:读入两个字符串常量,然后存储在res数组中,最后返回它的指针即可。
懒得写了
#include <stdio.h>
char *fun(char *a, char *b) {
char res[200];
("%s%s", a, b);
printf
return res;
}
int main(void) {
int ch, a[100], b[100], *res, i;
("%s %s", a, b);
scanf(a, b);
fun
return 0;
}
除了下面的解法,也可以严格按照题目要求来解:gechar
读入字符,再输出就行。
#include <stdio.h>
int main(void) {
int a;
("%d", &a);
scanf("%d", a);
printf
return 0;
}
实在是不知道这题存在的意义。。
如果是十三进制转十进制这样的,就有难度了。。
这个的解法可以参照我前面写的进制转换那篇,回头我也会再写一个更通用的。
#include <stdio.h>
int main(void) {
int a;
("%x", &a);
scanf("%d", a);
printf
return 0;
}
double function(int n) {
if (n == 1)
return 1.000000;
else
return 1.000000 / (1.000000 + function(--n));
}
int fib(int n)
{
if (n == 0)
return 7;
else if (n == 1)
return 11;
else
return fib(n - 1) + fib(n - 2);
}
#include <stdio.h>
int bit_sum(int num)
{
return num>=10?num%10+bit_sum(num/10):num;
}
int main(void)
{
int num;
("%d",&num);
scanfwhile(num>=10)
=bit_sum(num);
num("%d",num);
printf
return 0;
}
#include <stdio.h>
double mul(int num)
{
if(num>1)
return 1.0*num * mul(num-1);
else
return 1.0;
}
int main(void)
{
int m,n,tmp;
("%d %d",&m,&n);
scanfif(m<n)
=m,m=n,n=tmp;
tmp("%.2f",mul(m)/mul(n)/mul(m-n));
printf
return 0;
}
#include <stdio.h>
void tow(int ch,int line)
{
int i;
for(i=0;i<line;i++)
{
/* 1.print space */
for(int j=i;j<line-1;j++)
(' ');
putchar/* 2.print char */
for(int k=0;k<2*i+1;k++)
(k%2==0?ch:' ');
putchar/* 3.start a new line */
if(i!=line-1)
("");
puts}
}
int main(void)
{
int ch,n;
("%c %d",&ch,&n);
scanf(ch,n);
tow
return 0;
}
#include <stdio.h>
int main(void)
{
int ch[100],i=0;
while(ch[i]=getchar(),ch[i]!=EOF&&ch[i]!='\n')
++;
iwhile(i--)
(ch[i]);
putchar
return 0;
}
#include <stdio.h>
int is_prime(int num)
{
for(int i=2;i<num;i++)
if(num%i==0&&num!=2)
return 0;
return 1;
}
int main(void)
{
int num;
("%d",&num);
scanf("%s",is_prime(num)?"YES":"NO");
printf
return 0;
}
#include <stdio.h>
int fun(int num, int* arr);
int main(void)
{
int num,i,j=0,arr[64];
("%d",&num);
scanf("%d\n",i=fun(num,arr));
printfwhile(i-j)
("%d ",arr[j]),j++;
printf
return 0;
}
int fun(int num, int* arr)
{
int res=0;
for(int i=2;i<=num;i++)
{
int flag=1;
if(i==2);
else if(i>2)
for(int j=2;j<i;j++)
if(i%j==0)
=0;
flagif(flag)
*arr++=i,res++;
}
return res;
}
这题啥也没有,直接提交就行
估计是忘放题了
已经忘了是多少次练习了。。
之前写2048的时候写过类似算法
#include <stdio.h>
int main(void)
{
int arr[30][30], arr_new[30][30];
int m, n, i, j;
("%d %d", &m, &n);
scanffor (i = 0; i < m; i++)
for (j = 0; j < n; j++)
("%d", &arr[i][j]), arr_new[i][j] = arr[i][j];
scanffor (i = 0; i < m; i++)
{
int flag = 0;
for (j = 0; j < n - 1; j++)
{
if (arr[i][j] == arr[i][j + 1])
++;
flagelse
= 0;
flag if (flag >= 2)
[i][j - 1] = arr_new[i][j] = arr_new[i][j + 1] = 0;
arr_new}
}
for (j = 0; j < n; j++)
{
int flag = 0;
for (i = 0; i < m - 1; i++)
{
if (arr[i][j] == arr[i + 1][j])
++;
flagelse
= 0;
flag if (flag >= 2)
[i - 1][j] = arr_new[i][j] = arr_new[i + 1][j] = 0;
arr_new}
}
for (i = 0; i < m; i++)
{
for (j = 0; j < n; j++)
("%d ", arr_new[i][j]);
printf("");
puts}
return 0;
}
稍微解释下吧。一共四个for
循环,首尾两个负责输入输出,中间两个分别用于处理每一行和每一列。
处理思路很简单,参考第一题。
代码很丑,本想重构一下,抽个函数出来,结果让指针绊住了。。还是学艺不精.jpg
#include <stdio.h>
#include <stdlib.h>
int bit_sum(int num);
int compare(int a, int b);
int main(void)
{
int i, j, n, *arr, tmp;
("%d", &n);
scanf= (int *)malloc(sizeof(int) * n);
arr for (i = 0; i < n; i++)
("%d", &arr[i]);
scanffor (i = 0; i < n - 1; i++)
for (j = i + 1; j < n; j++)
if (compare(arr[i], arr[j]) < 0||(compare(arr[i], arr[j]) == 0&&arr[i] > arr[j]))
= arr[i], arr[i] = arr[j], arr[j] = tmp;
tmp for (i = 0; i < n; i++)
("%d %d\n", arr[i], bit_sum(arr[i]));
printf
return 0;
}
int bit_sum(int num)
{
int res = 0;
while (num)
+= num % 10, num /= 10;
res
return res;
}
int compare(int a, int b)
{
return bit_sum(a) > bit_sum(b)?1:bit_sum(a) == bit_sum(b)?0:-1;
}
bit_sum
是计算各位和的函数,compare
是比较两个数各位和大小的函数。逻辑在主程序中完成。
#include <stdio.h>
#include <stdlib.h>
void sort(int *arr, int len);
int main(void)
{
int n, *arr, *res, i, j;
("%d", &n);
scanf= (int *)malloc(sizeof(int) * n * 2 + 2);
res = (int *)malloc(sizeof(int) * n * n);
arr for (i = 0; i < n * n; i++)
("%d", &arr[i]);
scanffor (i = 0; i < n; i++)
for (res[i] = 0, j = 0; j < n; j++)
[i] += arr[i * n + j];
resfor (; i < n * 2; i++)
for (res[i] = 0, j = 0; j < n; j++)
[i] += arr[i - n + j * n];
resfor (j = res[i] = res[i + 1] = 0; j < n; j++)
{
[i] += arr[j + j * n];
res[i + 1] += arr[n - 1 - j + j * n];
res}
(res, n * 2 + 2);
sortfor (i = 0; i < n * 2 + 2; i++)
("%d ", res[i]);
printf
return 0;
}
void sort(int *arr, int len)
{
int i, j, tmp;
for (i = 0; i < len - 1; i++)
for (j = i + 1; j < len; j++)
if (arr[i] < arr[j])
= arr[i], arr[i] = arr[j], arr[j] = tmp;
tmp }
大概算了一下规律,然后用一维数组解决了。
比较有意思的一个是,我们可以把这个sort
函数改进一下,变成一个更通用的排序函数。这样,上一个题也能用它解决了。
上代码:
void sort(int *arr, int len,int (*cmp)(int a,int b))
{
int exchange(int *a,int *b){int i;i=*a,*a=*b,*b=i;}
int i, j, tmp;
for (i = 0; i < len - 1; i++)
for (j = i + 1; j < len; j++)
if (arr[i] < arr[j])
(&arr[i], &arr[j]);
exchange}
这里的函数嵌套是C语言支持但不推荐的特性。我用gcc
可以编译。
用它来解决上一题:
#include <stdio.h>
#include <stdlib.h>
int compare(int a, int b);
void sort(int *arr, int len,int (*cmp)(int a,int b));
int bit_sum(int num){return res>0?res%10+bit_sum(res/10):0;}
int main(void)
{
int i, j, n, *arr, tmp;
("%d", &n);
scanf= (int *)malloc(sizeof(int) * n);
arr for (i = 0; i < n; i++)
("%d", &arr[i]);
scanf(arr, n, cmp_bit_sum);
sortfor (i = 0; i < n; i++)
("%d %d\n", arr[i], bit_sum(arr[i]));
printf
return 0;
}
int cmp_bit_sum(int a, int b)
{
return bit_sum(a) > bit_sum(b)?1:bit_sum(a) == bit_sum(b)?0:-1;
}
void sort(int *arr, int len,int (*cmp)(int a,int b))
{
int exchange(int *a,int *b){int i;i=*a,*a=*b,*b=i;}
int i, j;
for (i = 0; i < len - 1; i++)
for (j = i + 1; j < len; j++)
if (arr[i] < arr[j])
(&arr[i], &arr[j]);
exchange}
#include <stdio.h>
int is_rev(int num);
int bit_sum(int num);
int get_bit(int num, int bit)
{
int xpow(int a, int b) { return b > 0 ? a * xpow(a, b - 1) : 1; }
return (num % (xpow(10, bit)) - num % (xpow(10, bit - 2))) / xpow(10, bit - 1);
}
int main(void)
{
int num;
("%d", &num);
scanfif (is_rev(num))
("%d", bit_sum(num));
printfelse
("no");
printf
return 0;
}
int is_rev(int num)
{
int origin = num, bit = 0, i, end = 0;
if (num == 0)
return 1;
else
while (bit++, num /= 10);
= origin;
num for (i = 1, end = bit % 2 == 0 ? bit / 2 : (bit - 1) / 2; i <= end; i++)
if (get_bit(num, i) != get_bit(num, bit - i + 1))
return 0;
return 1;
}
int bit_sum(int num)
{
int res = 0;
while (res += num % 10, num /= 10);
return res;
}
这题思路很多,愿意的话也可以用字符串处理来完成。
总是自己写pow
是因为我这边本地环境里pow
好像是坏的。。