Codeforces Round #538 (Div. 2) C. Trailing Loves (or L'oeufs?) (分解质因数)

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

猜你喜欢

转载自www.cnblogs.com/Lis-/p/10730978.html
今日推荐