现在的位置: 首页 > 综合 > 正文

【算法入门】简单练习

2019年04月23日 ⁄ 综合 ⁄ 共 1328字 ⁄ 字号 评论关闭

(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;
}

抱歉!评论已关闭.