第二章 循环结构程序设计–算法竞赛入门经典
例题2-2:3n+1的溢出问题
int32位整数范围是-2147473648~2147483647,long long是64位的整形可以表示的范围是-2^63 ~ 2^63-1。
#include<stdio.h>
int main()
{
int n2, count = 0;
scanf("%d", &n2);
long long n = n2;
while (n > 1)
{
if (n % 2 == 1)
{
n = n * 3 + 1;
}
else
{
n /= 2;
}
count++;
}
printf("%d\n", count);
return 0;
}
输入987654321
输出180
例题2-4:阶乘之和 P25
输入n,计算S=1!+2!+3!+…+n!的末6位(不含前导0),n<=10^6。
#include<stdio.h>
#include <stdio.h>
#include <time.h>
int main()
{
const int MOD = 1000000;
int n, s = 0;
scanf("%d", &n);
if (n>25)/*程序的运行时间大致和n的平方成正比。因为25!的末尾
有6个零,所以n=25之和的输出都一样。加上n>25的判断,解决效率和溢出问题。*/
{
n = 25;
}
for (int i = 1;i <= n;i++)
{
int factorial = 1;
for (int j = 1;j <= i;j++)
{
factorial = factorial*j%MOD;
}
s = (s + factorial) % MOD;
}
printf("%d\n", s);
printf("Time used = %.2fs\n", (double)clock() / CLOCKS_PER_SEC);
/*使用time.h和clock()函数获得程序运行时间。常数CLOCKS_PER_SEC和操作系
统相关,请不要直接使用clock()的返回值,而应总是除以CLOCKS_PER_SEC。*/
/*为了避免输入数据的时间影响测试结果,可使用一种称为“管道”的小技巧:
在Windows命令行下执行echo 20|abc,操作系统会自动把20输入,其中abc是程序名。*/
return 0;
}
例题2-5:数据统计 P27
输入一些整数,求出它们的最小值、最大值和平均值(保留3位小数)。输入保证这些数都是不超过1000的整数。
数据统计(重定向版):
#include <stdio.h>
#define LOCAL
#define INF 1000000000
int main()
{
#ifdef LOCAL
freopen("input.txt", "r", stdin);
freopen("output.txt", "w", stdout);
#endif
int a;
int min = INF;
int max = -INF;
int n = 0;
int s = 0;
//在Windows下,输入完毕后,需要键入Ctrl+Z,之后再按Enter键,即可结束输入。
while (scanf("%d", &a) == 1)//scanf返回成功输入的变量个数
{
if (a < min)
min = a;
if (a > max)
max = a;
s += a;
n++;
}
double avg;
avg = double(s) / n;
printf("%d %d %.3lf\n", min, max, avg);
return 0;
}
数据统计(fopen版):
#include <stdio.h>
#define INF 1000000000
int main()
{
FILE *fin, *fout;
fin = fopen("input.txt", "rb");
fout = fopen("output.txt", "wb");
int x, n = 0, min = INF, max = -INF, s = 0;
while (fscanf(fin, "%d", &x) == 1)
{
s += x;
if (x < min)
min = x;
if (x > max)
max = x;
n++;
}
fprintf(fout, "%d %d %.3f\n", min, max, (double)s / n);
fclose(fin);
fclose(fout);
return 0;
}
数据统计(fopen+标准输入输出版):
#include <stdio.h>
#define INF 1000000000
int main()
{
FILE *fin, *fout;
//在文件操作下用标准输入输出的方法一
//fin = fopen("con", "rb");
//fout = fopen("con", "wb");
//在文件操作下用标准输入输出的方法二
fin = stdin;
fout = stdout;
int x, n = 0, min = INF, max = -INF, s = 0;
while (fscanf(fin, "%d", &x) == 1)
{
s += x;
if (x < min)
min = x;
if (x > max)
max = x;
n++;
}
fprintf(fout, "%d %d %.3f\n", min, max, (double)s / n);
//用标准输入输出可以不用fclose
//fclose(fin);
//fclose(fout);
return 0;
}
习题2-5:分数化小数(decimal)
输入正整数a,b,c,输出a/b的小数形式,精确到小数点后c位。a,b<=10^6,c<=100。输入包括多组数据,结束标记为a=b=c=0。
#include <stdio.h>
int main()
{
freopen("input.txt", "r", stdin);
freopen("output.txt", "w", stdout);
int a, b, c;
int n = 0;
while (scanf("%d", &a) == 1 && scanf("%d", &b) == 1 && scanf("%d", &c) == 1)
{
if (a == 0 && b == 0 && c == 0)
break;
int res1, res2;
res1 = a / b;
res2 = a % b * 10;
if (c > 0)
{
printf("Case %d: %d.", ++n, res1);
for (int i = 0;i < c;i++)
{
res1 = res2 / b;
res2 = res2 % b * 10;
printf("%d", res1);
}
printf("\n");
}
else
{
printf("Case %d: %d\n", ++n, res1);
}
}
return 0;
}
习题2-6:排列(permutation)
用1,2,3,…,9组成3个三位数abc,def,ghi,每个数字恰好使用一次,要求abc:def:ghi=1:2:3。按照“abc def ghi”的格式输出所有解。
#include <stdio.h>
#include<string.h>
int main()
{
int abc, def, ghi;
int s[10] = { 0 };
for (int abc = 123;abc <= 329;abc++)//abc的最大值为987/3=329
{
memset(s, 0, sizeof(s));
int sum = 0;
def = abc * 2;
ghi = abc * 3;
s[abc / 100] = s[abc % 100 / 10] = s[abc % 10] = 1;
s[def / 100] = s[def % 100 / 10] = s[def % 10] = 1;
s[ghi / 100] = s[ghi % 100 / 10] = s[ghi % 10] = 1;
for (int i = 1;i < 10;i++)
{
sum += s[i];
}
if (sum == 9)
{
printf("%d %d %d\n", abc, def, ghi);
}
}
return 0;
}