【洛谷十月月测】 P3927 SAC E#1

题目传送门:https://www.luogu.org/problemnew/show/P3927

题目大意:给你两个正整数n,k,求n!在k进制下末尾零的数量。

我们通过简单的数学分析,便可以发现,n!可以化为x*k^y(x,y∈N),而末尾零的数量,正是y。

经过进一步化简,$n! = x*prod_{1}^{d(k)}d_{i}*y_{i}$,其中$d_{i}$为k的素因子,此处d(k)表示k的素因子个数,在已知d的情况下,求$y$并不复杂。

同时,我们也可以将k也化为这个格式,$k = *prod_{1}^{d(k)}d_{i}*y'_{i}$。

通过进一步的归纳,我们发现:末尾零的数量为$min(left lfloor  y_{i}/y'_{i}     ight floor)$。此题我们只需要求出$d_{i}$,随后求出$y_{i}$和$y‘_{i}$,最后简单计算即可得出答案。

考虑到$k≤10^{12}$,如果用常规的方法进行分解质因数求出所有$d_{i}$显然不行,于是我们用pollard_rho进行分解质因数即可。

如果你不知道什么是pollard_rho,传送门:http://blog.csdn.net/maxichu/article/details/45459533

时间复杂度为$O(k^{0.25}*log(n)*d(k))$

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #define L long long
 5 #include<algorithm>
 6 #include<map>
 7 using namespace std;
 8 L gcd(L x,L y){return y==0?x:gcd(y,x%y);}
 9 L mul(L x,L y,L MOD){
10     L ans=0;
11     while(y){
12         if(y&1) ans=(ans+x)%MOD;
13         y=y>>1; x=(x<<1)%MOD;
14     }
15     return ans;
16 }
17 bool pow(L x,L y,L MOD){
18     L ans=1;
19     while(y){
20         if(y&1) ans=mul(ans,x,MOD);
21         y=y>>1; x=mul(x,x,MOD);
22     }
23     return ans!=1;
24 }
25 bool check(L n){
26     if(n==2) return 1; if(n<2||n%2==0) return 0;
27     int t=20; while(t--) if(pow(1+rand()%(n-1),n-1,n)) return 0;
28     return 1;
29 }
30 L pollard_rho(L n,L c){
31     L x=1+rand()%(n-1),y=x,k=2;
32     for(int i=1;;i++){
33         x=(mul(x,x,n)+c)%n;
34         L d=gcd((y-x+n)%n,n);
35         if(d>1) return d;
36         if(x==y) return n;
37         if(i==k) y=x,k<<=1;
38     }
39 }
40 map<L,int> m;
41 void find(L n,L c){
42     if(n==1) return;
43     if(check(n)){m[n]++; return;}
44     L p=n; while(p>=n) p=pollard_rho(n,c--);
45     find(p,c); find(n/p,c);
46 }
47 L get(L n,L d){
48     L ans=0;
49     while(n) ans+=n/d,n=n/d;
50     return ans;
51 }
52 
53 int main(){
54     L n,k,minn=1e18; cin>>n>>k; find(k,2333333);
55     for(map<L,int>:: iterator it=m.begin();it!=m.end();it++){
56         L num=it->first,sum=it->second;
57         minn=min(minn,get(n,num)/sum);
58     }
59     cout<<minn<<endl;
60 }
原文地址:https://www.cnblogs.com/xiefengze1/p/7741511.html