zoukankan      html  css  js  c++  java
  • 【Luogu】P3927 SAC E#1

    【题目】洛谷10月月赛R1 提高组

    【题意】求n!在k进制下末尾0的个数,n<=1e18,k<=1e16。

    【题解】考虑10进制末尾0要考虑2和5,推广到k进制则将k分解质因数。

    每个质因数在n!中的数量,以2为例是n/2+n/4+n/8...这样统计。(含x个就被统计x次)

    最后得到凑出的k的个数就可以得到末尾0的个数。

    分解质因数复杂度O(√k),也使用pollard rho算法可以加速。

    #include <iostream>
    #include <stdlib.h>
    #include <string.h>
    #include <algorithm>
    #include <stdio.h>
    
    const int Times = 10;
    const int N = 5500;
    
    using namespace std;
    typedef long long LL;
    
    LL ct, cnt;
    LL fac[N], num[N];
    
    LL gcd(LL a, LL b)
    {
        return b? gcd(b, a % b) : a;
    }
    
    LL multi(LL a, LL b, LL m)
    {
        LL ans = 0;
        a %= m;
        while(b)
        {
            if(b & 1)
            {
                ans = (ans + a) % m;
                b--;
            }
            b >>= 1;
            a = (a + a) % m;
        }
        return ans;
    }
    
    LL quick_mod(LL a, LL b, LL m)
    {
        LL ans = 1;
        a %= m;
        while(b)
        {
            if(b & 1)
            {
                ans = multi(ans, a, m);
                b--;
            }
            b >>= 1;
            a = multi(a, a, m);
        }
        return ans;
    }
    
    bool Miller_Rabin(LL n)
    {
        if(n == 2) return true;
        if(n < 2 || !(n & 1)) return false;
        LL m = n - 1;
        int k = 0;
        while((m & 1) == 0)
        {
            k++;
            m >>= 1;
        }
        for(int i=0; i<Times; i++)
        {
            LL a = rand() % (n - 1) + 1;
            LL x = quick_mod(a, m, n);
            LL y = 0;
            for(int j=0; j<k; j++)
            {
                y = multi(x, x, n);
                if(y == 1 && x != 1 && x != n - 1) return false;
                x = y;
            }
            if(y != 1) return false;
        }
        return true;
    }
    
    LL pollard_rho(LL n, LL c)
    {
        LL i = 1, k = 2;
        LL x = rand() % (n - 1) + 1;
        LL y = x;
        while(true)
        {
            i++;
            x = (multi(x, x, n) + c) % n;
            LL d = gcd((y - x + n) % n, n);
            if(1 < d && d < n) return d;
            if(y == x) return n;
            if(i == k)
            {
                y = x;
                k <<= 1;
            }
        }
    }
    
    void find(LL n, int c)
    {
        if(n == 1) return;
        if(Miller_Rabin(n))
        {
            fac[ct++] = n;
            return ;
        }
        LL p = n;
        LL k = c;
        while(p >= n) p = pollard_rho(p, c--);
        find(p, k);
        find(n / p, k);
    }
    
    int main()
    {
        LL n,kind;
        scanf("%lld%lld",&kind,&n);
        ct = 0;
        find(n, 120);
        sort(fac, fac + ct);
        num[0] = 1;
        int k = 1;
        for(int i=1; i<ct; i++)
        {
            if(fac[i] == fac[i-1])
                ++num[k-1];
            else
            {
                num[k] = 1;
                fac[k++] = fac[i];
            }
        }
        cnt = k;
        LL ans=(1ll<<60);
        for(int i=0;i<cnt;i++){
            LL as=0,N=kind/fac[i];
            while(N){
                as+=N;
                N/=fac[i];
            }
            as/=num[i];
            ans=min(as,ans);
        }
        if(ans==1ll<<60)ans=0;
        printf("%lld",ans);
        return 0;
    }
    View Code
  • 相关阅读:
    洛谷 1996——约瑟夫问题(线性数据结构)
    洛谷 1219——[USACO 1.5] 八皇后(深度优先搜索)
    洛谷 1162——填涂颜色(广度优先搜索)
    洛谷 1803——凌乱的yy(贪心)
    洛谷 1094——纪念品分组(贪心)
    洛谷 1223——排队接水(贪心)
    洛谷 1028——[USACO 1.3]混合牛奶 Mixing Milk
    洛谷 1181——数列分段Section I(贪心)
    洛谷 1090——合并果子(贪心)
    洛谷 1012——拼数(字符串处理)
  • 原文地址:https://www.cnblogs.com/onioncyc/p/7638064.html
Copyright © 2011-2022 走看看