题目链接:http://codeforces.com/contest/1114/problem/C
题目大意:给你n和b,让你求n的阶乘,转换成b进制之后,有多少个后置零。
具体思路:首先看n和b,都比较大,肯定不能暴力做的,然后我们就想能不能通过分解质因数的方法来进行,当阶乘的值有多少b时,就会有多少满足情况的0。
当b是10的时候,可以分解成5*2,那么我们就求哪一个中,在n!中的个数最少,计算公式:
n的阶乘中素因子p的个数:
f(n)=⌊n/p⌋+⌊n/(p^2)⌋+⌊n/(p^3)⌋+⋯
当n为4,n的阶乘是24,b为4,24的二进制表示方法是16+8,最终算出来的后置0的个数是3,按照上面的公式,因子是2,f(4)=3,因为4是2的平方,所以还需要除以2,,按照进制就很好理解了。
PS:这个题在寻找最小值的时候,一定要注意初始值大一点啊,我一开始赋值1e18还不够,9e18才差不多的。。。
AC代码:
1 #include<iostream> 2 #include<stack> 3 #include<stdio.h> 4 #include<map> 5 #include<cstring> 6 #include<string> 7 #include<cmath> 8 #include<queue> 9 #include<algorithm> 10 using namespace std; 11 # define lson l,m,rt<<1 12 # define rson m+1,r,rt<<1|1 13 # define ll long long 14 const int maxn = 1e5+100; 15 ll sto1[maxn],sto2[maxn]; 16 ll sto3[maxn]; 17 ll cal(ll t1,ll t2) 18 { 19 ll tmp=0; 20 while(t2) 21 { 22 tmp+=(t2/t1); 23 t2/=t1; 24 } 25 return tmp; 26 } 27 int main() 28 { 29 ll n,m,tmp; 30 scanf("%lld %lld",&n,&m); 31 tmp=m; 32 int num=0; 33 for(ll i=2; i*i<=m; i++) 34 { 35 int res=0; 36 if(tmp%i==0) 37 { 38 sto1[++num]=i; 39 while(tmp%i==0) 40 { 41 tmp/=i; 42 res++; 43 } 44 sto2[num]=res; 45 } 46 } 47 if(tmp!=1)sto1[++num]=tmp,sto2[num]=1; 48 for(int i=1; i<=num; i++) 49 { 50 sto3[i]=cal(sto1[i],n); 51 // cout<<sto1[i]<<" "<<sto2[i]<<" "<<sto3[i]<<endl; 52 } 53 ll minn=9e18+1; 54 for(int i=1; i<=num; i++) 55 { 56 minn=min(minn,sto3[i]/sto2[i]); 57 } 58 printf("%lld ",minn); 59 return 0; 60 }