题目链接: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;
}