Codeforces Round #538 (Div. 2) C. Trailing Loves (or L'oeufs?) 【数论】

版权声明:如需转载,记得标识出处 https://blog.csdn.net/godleaf/article/details/88295226

题目链接:http://codeforces.com/contest/1114/problem/C

一个十进制数的二进制展开式中,次幂最小的那个数就是这个二进制数中末尾0的个数,所以题目的问题可以改成求某进制数的展开式中最小的那个次幂,也就是 n! % (b^r) == 0,满足这个式子的情况下,r能取的最大值。

这道题有一个结论非常重要,如果你不知道的话,是做不出来的。

假设 n!= p1^x1 * p2^x2 * p3^x3,p代表的是素数,x代表素数的次幂,那么求一个阶乘的某个素数的次幂怎么求?

ans = n/p + n/(p^2) + n/(p^3)。也就是累加 n/p 的结果,并且 n /= p,直到n == 0,那么累加的结果就是某阶乘的某个素数的次幂值。

另外代码里面有一些需要注意的注释。

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

int main(void)
{
    ll n, b;
    cin >> n >> b;
    ll ans = 1000000000000000000, bb = b, nn, tmp, cnt;
    for(ll i = 2; i <= sqrt(b); ++i) {
        if(bb%i == 0) {
            cnt = 0; tmp = 0;
            while(bb%i == 0) { bb /= i; tmp++; } // tmp求的是 b 的某个素数的次幂,在计算n!的素数次幂的时候要除去b本身的次幂数
            nn = n;
            while(nn) {
                cnt += nn/i; nn /= i;
            }
            ans = min(ans, cnt/tmp);
        }
    }
    if(bb > 1) { // 争对自己本身就是个素数的情况,因为上面的循环是从 2 到 sqrt(b)的,如果自己本身就是素数,显然就会漏掉自己。
        cnt = 0; nn = n; // 如果自己不是素数,那么所有的素数一定是在 sqrt(b) 以内的
        while(nn) {
            cnt += nn/bb; nn /= bb;
        }
        ans = min(ans, cnt);
    }
    cout << ans << endl;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/godleaf/article/details/88295226
今日推荐