題解 洛谷 P2388 階乘之乘 (doing)
阿新 • • 發佈:2021-07-11
E
目錄
因子(笑)
md CF 要開始了寫不了了
簡要題意
求 \(1!\times 2!\times \cdots\times n!\) 的末尾有幾個 \(0\) .
\(n\le 10^8\)
題解
主要思路
首先,一個數末尾有幾個零等價於它有多少個因子 \(10\) .
即這個數有多少個因子 \(2\) 和 \(5\),又因為因子 \(5\) 的數量少於因子 \(2\) 的數量,所以只需統計因子 \(5\) 的數量 .
注意,\(25\) 有兩個 \(5\)
一個 \(o(n)\) 的演算法
這裡確實是小寫 \(o\)!!表示下界!其實只是因為我不會算這個時間複雜度233
就是平凡的去除因子 \(5\) 即可 .
一個 \(O(\log n)\) 的演算法
這裡講的通俗一些 .
列舉 \(5\) 的方冪 \(5^k\) .
對於每個 \(i\) 計算 \(i!\) 的貢獻,顯然是 \(\left\lfloor\dfrac{i}{5^k}\right\rfloor\) .
那個下取整是 \(1,2,3,\cdots\) 重複 \(5^k\) 次的結果,用個等差數列求和就可解決!!
一個演算法
其實這個題在 OEIS 上式能搜到的:http://oeis.org/A173345
但是我沒找到 \(O(1)\) 公式 /xk
程式碼
演算法 \(1\)(\(o(n)\))
// 初始 t=0, s=0, ans=0
for (int i=1;i<=n;i++)
{
t=i;
while (!(t%5)){++s; t/=5;}
ans+=s;
}
演算法 \(2\)
// 初始 now=5, ans=0
while (now<=n)
{
ll t=n;
while (t%now!=now-1){ans+=t/now; --t;}
ans+=now*(t/now)*(t/now+1)/2;
now*=5;
}