题目:http://codeforces.com/problemset/problem/1114/C
题意:给你n,m,让你求n!换算成m进制的末尾0的个数是多少(1<n<1e18 1<m<1e12)
思路:首先我们想一下更简单的一个问题
n!下十进制的末尾0的个数是多少,我们要使末尾出现0,十进制下我们必定是要出现 2*5 或者 1*10才可以,10分成素因子其实也就是2*5,这个时候我们只要数一下1-n里面有多少
2,5因子即可
这个时候我们就能知道我们这题,我们首先求出m的所有素因子,然后分别求出在1-n的出现次数
因为我们要满足出现0,必定是所有素因子出现了一遍才满足出现一次,所以我们求因子出现次数最小的那个即可
#include<set> #include<cstdio> #include<iostream> #include<cstring> #include<cmath> #include<map> #include<vector> #define mod 1000007 #define maxn 100005 using namespace std; typedef long long ll; ll n,m; int vis[maxn]; vector<ll> mp; ll suan(ll x){//求出1-n因子的出现次数 ll sum=0; ll z=m; while(z){ sum+=z/x; z/=x; } return sum; } int main(){ cin>>m>>n; while(n!=1){//求出所有的因子 ll t=sqrt((double)n); ll i=2; for(;i<=t;i++){ if(n%i==0){ mp.push_back(i); n/=i; break; } } if(i==t+1){//剩下因子是素数的情况 mp.push_back(n); break; } } map<ll,ll> q; for(int i=0;i<mp.size();i++){ if(q[mp[i]]==0) q[mp[i]]=suan(mp[i]); } for(int i=0;i<mp.size();i++) { if(vis[i]) continue; int num=1; for(int j=i+1;j<mp.size();j++) { if(mp[j]==mp[i]){ num++; vis[j]=1; } } q[mp[i]]/=num;//因为素因子相乘里面有重复的,所以我要把出现次数/出现的位置,才能满足每个位置同时出现的正确性 } ll mn=q[mp[0]]; for(int i=1;i<mp.size();i++){ mn=min(mn,q[mp[i]]); } cout<<mn; }