题目:https://www.nowcoder.com/acm/contest/135/C
思路:
把m分解质因数,并存下每个质因数有几个。再看x!里有多少个这些质因数。取最小的倍数就是了。
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll inf=1e18;
ll f[11111];
int cnt;
int num;
int ans[15]= {0,1,0,0,2,10,4,40,92,352,724,2680,14200,73712,365596};
ll p[100];
bool pr[100];
ll a[105];
ll x;
ll m;
void init()
{
f[1]=1;
f[2]=1;
for(int i=3;;i++)
{
if(f[i-1]>inf-f[i-2])
{
cnt=i-1;
break;
}
else
{
f[i]=f[i-1]+f[i-2];
}
}
memset(pr,0,sizeof(pr));
num=1;
for(ll i=2;i<100;i++)
{
if(!pr[i])
{
p[num++]=i;
for(int j=i*2;j<=100;j+=i)
{
pr[j]=1;
}
}
}
}
ll findx(ll n)
{
ll now=n;
ll ans=0;
while(x>=now)
{
ans+=x/now;
now*=n;
}
return ans;
}
int main()
{
init();
scanf("%lld %d",&x,&m);
int flag=0;
for(int i=1;i<=cnt;i++)
{
if(f[i]>x)
{
break;
}
if(f[i]==x)
{
flag=1;
break;
}
}
if(!flag)
{
if(m>13)m=13;
x%=m;
x++;
printf("%d\n",ans[x]);
}
else
{
memset(a,0,sizeof(a));
int k=m;
for(int i=1;i<num;i++)
{
while(k%p[i]==0)
{
k/=p[i];
a[i]++;
}
}
ll minn=1e18;
//cout<<1<<endl;
for(int i=1;i<num;i++)
{
if(a[i]>0)
{
//cout<<p[i]<<' '<<a[i]<<endl;
minn=min(findx(p[i])/a[i],minn);
}
}
printf("%lld\n",minn);
}
return 0;
}