AcWing 寒假每日一题 2021-01-24 阶乘

AcWing 1381. 阶乘(传送门)
在这里插入图片描述
思路分析:
这里给提供两种参考思路

第一种
我们进行观察,因为0只可能由2的倍数和5的倍数相乘得到,所以在进行乘法的过程中,我们将2和5的倍数给清理掉,这样就保证了不会出现0,然后我们控制其范围,每次相乘取其个位,因为个位肯定是非零元素,十位以后的数字完全没有必要保留下来,最后,我们将多处理的2或者5重新乘回去再取余即可。

利用的知识有:数论中的约数、同余定理

AC代码:

#include <bits/stdc++.h>

#define ll long long

using namespace std;

int main() {
    
    
    int n;
    while (cin >> n) {
    
    
        int res = 1;
        int d2 = 0, d5 = 0;
        for (int i = 1; i <= n; i++) {
    
    
            int num = i;
            // 先处理掉 2 和 5
            while(num % 2 == 0) {
    
    
                num /= 2;
                d2++;
            }
            while(num % 5 == 0) {
    
    
                num /= 5;
                d5++;
            }
            // 前面的处理保证了个位不会出现 0 
            res = res * num % 10;
        }
        // 2 的因数要多余 5
        // 这里的话,处理一下多余的2
        for(int i = 0;i < d2 -d5;i++)
            res = res * 2 % 10;
        cout << res << endl;
    }
    return 0;
}

如果不放心 2 和 5 谁多的话,也可以选最小值处理下,但这貌似是个数论中约数的结论

        int k = min(d2,d5);
        for(int i = 0;i<d2-k;i++)
            res = res * 2 % 10;
        for(int i = 0;i<d5 - k;i++)
            res = res * 5 % 10;

第二种:
第二种是比较容易想到的思维
只要 MOD 给的合理就行 这里的话 N 的范围是 1-1000,然而 1000 * 1000 也最多6个0 ,所以 MOD 只要比 1e6大应该都可以(当然是在保证不溢出的情况下),保险起见给了个1e9 ,后实战测试 1e3 就能过

AC代码:

#include <bits/stdc++.h>

#define ll long long

using namespace std;

const int mod = 1e9;

int main() {
    
    
    int n;
    while (cin >> n) {
    
    
        ll res = 1;
        for(int i = 1;i<=n;i++) {
    
    
            res *= i;
            // 如果有尾数有 0 处理掉
            while(res % 10 == 0) {
    
    
                res /= 10;
            }
            res = res % mod;
        }
        // 最后只要非 0 的个位
        res = res % 10;
        cout << res << endl;
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_45654671/article/details/113099199
今日推荐