zoukankan      html  css  js  c++  java
  • 【洛谷十月月测】 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 }
  • 相关阅读:
    Html中,id、name、class、type的区别
    Windows10右键添加“在此处打开命令窗口”
    yarn的安装与使用及与npm对应的命令
    TodoMVC:帮助你选择一个MV*框架
    迅速上手:使用taro构建微信小程序基础教程
    编程之性能优化知多少
    CQRS
    事件驱动之异步事件
    事件驱动下
    事件驱动上
  • 原文地址:https://www.cnblogs.com/xiefengze1/p/7741511.html
Copyright © 2011-2022 走看看