noip模擬賽 SAC E#1 - 一道中檔題 Factorial
題目背景
數據已修改
SOL君(爐石主播)和SOL菌(完美信息教室講師)是好朋友。
題目描述
SOL君很喜歡階乘。而SOL菌很喜歡研究進制。
這一天,SOL君跟SOL菌炫技,隨口算出了n的階乘。
SOL菌表示不服,立刻就要算這個數在k進制表示下末尾0的個數。
但是SOL菌太菜了於是請你幫忙。
輸入輸出格式
輸入格式:
每組輸入僅包含一行:兩個整數n,k。
輸出格式:
輸出一個整數:n!在k進制下後綴0的個數。
輸入輸出樣例
輸入樣例#1:10 40輸出樣例#1:
2
說明
對於20%的數據,n <= 1000000, k = 10
對於另外20%的數據,n <= 20, k <= 36
對於100%的數據,n <= 10^12,k <= 10^12
update
1.一組數據
2.K不會==1
3.現在std沒有爆long long
4.對數據有問題聯系icy (建議大家不要面向數據編程)
分析:k=10就是一個非常經典的問題,將n!分解質因數,看看有多少個5就可以了.現在考慮k≠10的情況,模擬一下進制轉換,就是不斷地%k,/k,我們就是要求一開始k能整除n!多少次.
n!,k過大,顯然不能直接算,涉及到倍數,我們可以分解一下k,看看k的質因子是不是n!都有,並且n中的次數大於等於k中的次數.假設n!有一個因子p1,次數為b1,它在k中的次數為b2,每做一次除法就是b1-=b2,每次做除法後都必須保證k中的質因子n!都有,並且次數不能小於k中的.能做多少次除法呢?把相同質因子的次數相除,取個min就可以了.
還有一個問題:k可以直接分解質因數,但是n!就非常大了,我們根本算不出來,怎麽才能統計k中的每個質因數在n!中出現的次數呢?對於一個質因數p,1~n個數中有n / p個數包含這個質因子,有n / (p ^ 2)個數包含p^2,也就是相當於包含了p.我們求出包含了p^i的個數,最後相加一下就是答案了.因為階乘嘛,最後乘起來等於指數的相加.
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <cmath> usingnamespace std; long long n, k; long long cnt, p[1000010], tot[1000010], ans = 10000000000000000; void f(long long x) { for (long long i = 2; i * i <= x; i++) { if (x % i == 0) { p[++cnt] = i; while (x % i == 0) { tot[i]++; x /= i; } } } if (x != 1) { p[++cnt] = x; tot[x]++; } } long long cal(long long x, long long y) { //printf("%lld %lld\n", x, y); if (y > x) return 0; return x / y + cal(x / y, y); } int main() { scanf("%lld%lld", &n, &k); f(k); for (int i = 1; i <= cnt; i++) ans = min(ans, cal(n, p[i]) / tot[p[i]]); printf("%lld\n", ans); return 0; }
noip模擬賽 SAC E#1 - 一道中檔題 Factorial