(1)大数据 溢出引起的思考
例:求 1!+2!+3!+...+n! 的低3位。
最原始的方法:
#include <stdio.h>
int main()
{
const int MOD=100;//求低三位
int i,j,n,s=0;
scanf("%d",&n);
for (i=1;i<=n;i++)
{
int factorial=1;
for (j=1;j<=i;j++)
factorial*=j;
s+=factorial;
}
printf("%d\n",s%MOD);
return 0;
}
这种方法对 较少的数来说没有问题。 但是 稍微大一些的数 例 30 得出的 -7. 很显然溢出。
这里介绍简单方法。
中间循环改为
for (i=1;i<n;i++)
{
int factorial=1;
for (j=1;j<=i;j++)
{
factorial=(factorial*j%MOD);
}
s=(s+factorial)%MOD;
}
printf("%d",s); //此时的s即为 最终结果
关键算法 一: factorial=(factorial*j%MOD); 因为 只考虑第三位 ,每个乘积只需考虑第三位的乘积 即可,所以,每次循环得到的 乘积都进行 %MOD
关键算法 二: s=(s+factorial)%MOD 将所有数阶乘的第三位求和,求总和的第三位,因为总和仍可能 超高3位,所以每次的求和 也都进行 %MOD
这样做的目的是为了保证每次都存储较少的,且有用的数据位。
(2)通过简单的判断,减少算法的冗余
例:求斜边小于等于n的所有的直角三角形 边长的组合。
方法一:(最笨最直接的做法)3个边长分别从 1到n 进行判断。
方法二:确定一斜边和一直角边。直角边必定小于斜边,从而减少一部分冗余。
方法三:确定一斜边和一直角边,同时确定另一直角边的范围 必定小于等于 sqrt(斜边方-直角边平方)的整数部分。 (该边从小到大取值,超过一定只就不再可能满足 a2+b2=c2 b,c固定)
#include <iostream> #include <cmath> using namespace std; int main() { cout<<"input the num:"; int n,length(0); int longSquart(0),rectSquart(0); cin>>n; for (int i=1;i<=n;i++)//斜边 { longSquart=i*i; for (int j=1;j<i;j++)//一直角边 { rectSquart=j*j; length=(int)sqrt((double)(longSquart-rectSquart)); //for(int k=1;k<=n;k++) //方法一 //for (int k=1;(k<=length)&&(k<=j);k++) //方法二 可避免 5,4,3 5,,3,4式的重复计算 for (int k=j;k<=length;k++) //方法三: 缩小搜索的范围 { if ((k*k+rectSquart)==longSquart) { cout<<"Have the num:"<<i<<" "<<j<<" "<<k<<endl; } } } } return 0; }