最後更新日期 2024 / 01 / 01

題解 CSES Trailing Zeros

https://cses.fi/problemset/result/5470956/

題意

n 階乘求數字有幾個後綴 0

想法

不難發現
後綴幾個 0 就等於乘進去的 10 的個數
10=5×2
所以後綴 0 數量就相當於計算把每個數質因數分解後 5 和 2 的較少的那個的個數
那當然 5 一定會比 2 少
所以我們要做的是就是計算 5 的個數
那要如何計算呢?

以 30 為例
我們知道要求得 30 階就是要把下面這些數字乘起來

不過我們可以先排除掉質因數分解後裡面沒有 5 的數字
然後把下面的數字都各取走一個質因數分解裡面的 5(相當於除與 5)
並把答案加上 6 (因為下面有 6 個數字)

變成這樣
可以看到下面的數字剛好就是 6 階乘的子問題

像剛剛的作法一樣
把跟 5 無關的數字排除並把它取走一個 5 的質因數
答案 += 1

這樣就完成 30 階的計算了!

根據上面的操作
可以推出下列遞迴式

f(x)=f(nx)+nx

不過寫成程式其實用 while 迴圈就可以了

#include <bits/stdc++.h>
#define int long long
using namespace std;
signed main() {
    int n;
    cin >> n;
    if (n % 2) {
        cout << 0 << endl;
        return 0;
    }
    int ans = 0;
    while (n >= 5) {
        n /= 5;
        ans += n;
    }
    cout << ans << endl;
}

推薦文章

題解 CSES Permutations

給予一個數字 n 你要使用數字 1 sim n 構造一個陣列 使得不存在任意兩個相鄰數字的差為 1把 n 個數字分成 1 sim lfloor frac{n}{2} rfloor 和 lfloor frac{n}{2}+1 rfloor sim n 兩堆 並穿插構造 ans 陣列就可以保證任兩數的差大約為 lfloorfrac{n}{2}rfloor 最後跑過整個陣列驗證是否合法即可cppusing namespace std;signed main { iosbase::syncwithstdiofalse;cin.tie0; int n; cin n; vectorint arrn; dequeint ans; int mid = n2; for int i = 1; i = n2; i ++ { int leftVal = i; int rightVal = mid + i; ans.pushbackrightVal; ans.pushbackleftVal; } if n 1 == 1 { ans.pushfrontmid + n2 +1; } for int i = 0; i n-1; i++ { if absansi+1 - ansi == 1 { cout "NO SOLUTION" endl; return 0 ; } } for int i = 0; i n; i ++ { cout ansi " "; } cout endl;}

CSES

題解 CSES Weird Algorithm

給予一個數字 n 如果他是偶數就把他除 2 否則就把他乘 3 再加 1 重複直到 n 變成 1沒什麼特別的概念 直接模擬操作就可以了cppusing namespace std;signed main { int n; cin n; whilen = 1 { cout n " "; if n 1 == 1 { n = 3; n++; } else { n = 2; } } cout 1 endl;}

CSES

題解 CSES Common Divisors

找到兩個數字 使得兩數的最大公因數盡量大可以把題目想成 找到最大的 x 使得陣列中出現至少兩個他的倍數 於是我們可以先用 cnt 陣列紀錄每個數字的出現次數 然後枚舉每個可能的因數 假設目前枚舉到 k 從 k、2k、3k dots 計算陣列中存在多少個倍數 根據調和級數.harmonic-series可以算出時間複雜度為 On log ncppconst int maxn = 1e6 + 10;int cntmaxn;signed main { int n; cin n; vectorint vn; for int i = 0; i n; i++ { cin vi; cntvi++; } for int k = maxn; k 0; k-- { int cur = 0; for int j = k; j maxn; j += k { cur += cntj; } if cur = 2 { cout k endl; return 0; } }}

CSES