题目链接
http://icpc.upc.edu.cn/problem.php?cid=1882&pid=3
题意:
求n! 在k进制下末尾0的个数
题解:
可以知道
一个数N可以转换成a*(k^x) (k表示进制,x表示末尾0的个数)
即N=a*(k^x)
例如: 十进制 1300 =13*(10^2)
二进制 100 = 1*(2^2)
所以
N=a*(k^x)
由唯一分解定理得k=(b1^x1)*(b2^x2)*…*(bm^xm)
->N=a*((b1^x1)*(b2^x2)*…*(bm^xm))^x
->N=a*((b1^(x1*x))*(b2^(x2*x))*…*(bm^(xm*x)))
这里可以换一种表示形式
即N=Ai*(bi^Si) 其中 Ai=a*( (b1^(x1*x))*(b2^(x2*x))*(b(i-1)^(x(i-1)*x))*(b(i+1)^(x(i+1)*x))…*(bm^(xm*x))即除了第i项外其他的乘积
所以要求的x=Si/xi
这里存在N=A1*(b1^S1) N=A2*(b2^S2) ……
找一个最小值即可
其中对n! 中存在多少个p的理解,即对上面的式子中Si的求解
比如说8!=1*2*3*4*5*6*7*8 中有多少个2
其中 2,4,6,8 中存在4个具有2的质因子
2 3 4中存在2个具有2的质因子
2中存在1个具有2的质因子
所以总共8! 存在7个2
公式:
f(n)=(n/p)+(n/p/p)+(n/p/p/p)+…
#include<bits/stdc++.h>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<stdio.h>
#include<string.h>
#include<vector>
#include<map>
#include<set>
#include<stack>
#include<unordered_map>
#pragma GCC optimize(2)
#define debug cout<<"*"<<endl;
#define input(x) scanf("%d",&x)
#define output(x) printf("%d\n",x)
#define llinput(x) scanf("%lld",&x)
#define lloutput(x) printf("%lld\n",x)
using namespace std;
typedef long long ll;
typedef __int128 Biginteger;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
typedef pair<string,int> psi;
typedef pair<char,char> pcc;
const int mod=1e9+7;
const int INF=1e9+7;
const int maxn=1e6+7;
const double PI=acos(-1);
const int N=4;
ll prime[1000007];
ll cnt=0;
ll vis[1000007];
void get_pri(ll k) //唯一分解定理求k的因子和因子数量
{
for(ll i=2;i*i<=k;i++)
{
while(k%i==0)
{
prime[cnt]=i;vis[cnt]++;k/=i;
}
if(prime[cnt]) cnt++;
}
if(k>1) prime[cnt]=k,vis[cnt++]=1;
}
ll get_cot(ll n,ll pri) //求n! 中存在多少个pri
{
ll res=0;
while(n>0)
{
res+=n/pri;
n/=pri;
}
return res;
}
int main()
{
ll n,k;
ll ans=1e18+7;
cin>>n>>k;
get_pri(k);
for(ll i=0;i<cnt;i++) //遍历找最小值
{
ans=min(ans,get_cot(n,prime[i])/vis[i]);
}
cout<<ans<<endl;
return 0;
}
学习博客:
https://www.e-learn.cn/content/qita/2008269
https://www.jianshu.com/p/ee73fdfaa8e1