1. 程式人生 > 其它 >題解 洛谷 P2388 階乘之乘 (doing)

題解 洛谷 P2388 階乘之乘 (doing)

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

演算法 \(3\)