FOR
- 对于for循环,建议尽量缩短变量的定义范围,例如在初始化部分定义循环变量。
for(int i=0;i<10;i++)
aabb(7744)
输出所有形如aabb的4位完全平方数;
#include<stdio.h>
#include<math.h>
int main()
{
for(int a=1;a<=9;a++)
{
for(int b=1;b<=9;b++)
{
int n=a*1100+b*11;//这里才开始使用n,因此在这里定义n
int m=floor(sqrt(n)+0.5);//函数floor(x)返回不超过x的最大整数
if(m*m==n) printf("%d\n",n);
}
}
return 0;
}
函数floor(x)返回不超过x的最大整数 ,理论上乐意直接判断sqrt(n)是否为整数,但是浮点运算可能出现误差,整数1会变成0.9999999999,floor(sqrt(n))的结果可能就是0而不是1了所以改成四舍五入,即floor(sqrt(n)+0.5);
另一个思路是枚举平方根,从而避免开方操作
#include<stdio.h>
int main()
{
for(int x=1;;x++)
{
int n=x*x;
if(n<1000) continue;
if(n>9999) break;
int hi=n/100;
int lo=n%100;
if(hi/10==hi%10 && lo/10==lo%10) printf("%d\n",n);
}
return 0;
}
while & do-while
3n+1问题
猜想:对于任意大于1的自然数n,若n为奇数,则将n变为3n+1,否则变为n的一半。经过若干次这样的变换,一定会使n变为1。
输入n,输出变换的次数;n<10^9
流行的平台中:int都是32位整数-2^31~2^31-1
这道题就要考虑乘法溢出的问题了,n<10^9只比int的上界小一点,3n+1肯定会溢出;
int不够用,可以使用C99中的long long(-2^63~2^63-1),但是long long的输入输出方法有点奇怪(有的用%lld,有的用%I64d),所以遇到long long,常用C++的输入输出流cin cout。
#include<stdio.h>
int main()
{
int n2,count=0;
scanf("%d",&n2);
long long n=n2;
while(n>1)
{
if(n%2==1) n=3*n+1;
else n/=2;
count++;
}
printf("%d\n",count);
return 0;
}
循环终止判断是在计算之后,而不是在计算之前,适合使用do-while;
循环的代价
阶乘之和
输入n,计算S=1!+2!+3!+…+n!的末六位(不含前导0)。n<=10^6;
#include<stdio.h>
#include<time.h>
int main()
{
const int MOD = 1000000;
int n,S=0;
scanf("%d",&n);
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 = %.2f\n",(double)clock()/CLOCKS_PER_SEC);
return 0;
}
要计算只包含加减法,乘法的整数表达式除以正整数n的余数,可以在每步计算之后对n取余,结果不变。
计时函数clock()(#include<time.h>
)返回程序目前为止的运行时间,这个时间除以常数CLOCKS_PER_SEC之后得到的值以“秒”为单位。
循环结构中最常见的两个问题:
1. 算术运算溢出
2. 程序效率低下
算法竞赛中的输入输出框架
while(scanf("%d",&x)==1)
scanf的返回值是成功输入的变量数,当输入结束时,scanf函数无法再次读取x,将返回0;
对于scanf的输入格式,空格,tab和回车符都是无关紧要的,所以按enter并不意味着输入的结束。
在windows下,输入完毕后先按enter,再按ctrl+Z键,最后再按enter即可结束输入;
使用文件输入输出
- 使用文件最简单的方法是使用输入输出重定向,只需在main函数的入口处加入以下两条语句:
freopen("input.txt", "r", stdin);
freopen("output.txt", "w", stdout);
上述语句使得scanf从文件input.txt读入,printf写入文件output.txt.
- 文件输入输出(禁止使用重定向)
#include<stdio.h>
#define INF 10000000000
int mian()
{
FILE *fin, *fout;
fin = fopen("data.in","rb");
fout = fopen("data.out","wb");
int x,n=0,min=INF,max=-INF,s=0;
while(fscanf(fin, "%d",&x)==1)
{
/*循环语句*/
}
fprintf(fout, "%d\n",max );
fclose(fin);
fclose(fout);
return 0;
}
如果想把fopen版的程序改成读写标准输入输出,只需赋值
fin=stdin; fout=stdout;
即可,不要调用fopen和fclose;