学习笔记:乘法溢出问题

学习笔记:乘法溢出问题

1、3n+1问题
对于任意大于1的自然数,若n为奇数就将n变为3n+1,否则变为n的一半。当n变为1时,进行了多少次变换?
程序一:

#include<iostream>
#include<cstdio>
using namespace std;
int main()
{
    int n;
    int count=0;
    cin>>n;
    while(n>1)
    {
        if(n%2==0)
            n=n/2;
        else
            n=3*n+1;
        count++;
    }
    cout<<count<<endl;
    return 0;
}
此程序看似没问题,但当输入比int上界小一点点的n时,会乘法溢出。
可以用以下程序解决

程序二:

#include<iostream>
#include<cstdio>
using namespace std;
int main()
{
    long long n;
    int count=0;
    cin>>n;
    while(n>1)
    {
        if(n%2==0)
            n=n/2;
        else
            n=3*n+1;
        count++;
    }
    cout<<count<<endl;
    return 0;
}

二、阶乘之和问题
计算S=1!+2!+……+n!的末六位。
程序一:

#include<iostream>
#include<cstdio>
using namespace std;
int main()
{
    int n;
    int sum=0;
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        int factorial=1;
        for(int j=i;j>=1;j--)
            factorial=factorial*j;
        sum+=factorial;
    }
    printf("%d\n",sum%1000000);
    return 0;
}

当输入n=100时,输出-961703,说明乘法又溢出了,要解决这个问题,需要一个数学知识:计算只包含乘法加法减法的表达式时,对表达式除余,可以对每步计算除余,结果是不变的。
程序二:

#include<iostream>
#include<cstdio>
using namespace std;
int main()
{
    int n;
int sum=0;
const int MOD=1000000;
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        int factorial=1;
        for(int j=i;j>=1;j--)
            factorial=factorial*j%MOD;
        sum+=factorial%MOD;
    }
    printf("%d\n",sum);
    return 0;
}