题目描述很简单,给你正整数 n 、m,求一个最大的正整数 k使 n! 能被 m k m^k mk 整除。
Input
有多组数据,第一行输入一个整数 T(T<500)代表有 T组数据.
接下来每行输入一组数据,n(0<n<10000) ,m(1< m<5000).
Output
对应每组数据,输出一个最大的正整数 k 使 n!能被 m k m^k mk整除,若不存在这样的正整数,则输出 −1.
Examples
Input
2
10 2
100 2
Output
8
97
思路
因为10000!很大 我们不能求出来 ,所以我们不能直接算。 我们可以求出n和m的公共质因子,从而求出结果。
代码
#include<iostream>
#include<stdio.h>
#include<math.h>
using namespace std;
int a[5001];
int b[5001];
int size;
void Init()
{
size=0;
for(int i=2;i<=5000;i++)
{
if(a[i]==1) continue;
b[size++]=i;
if(a[i]==0){
for(int j=i*i;j<=5000;j+=i){
a[j]=1;
}
}
}
}///求1-1000所有的素数
int main()
{
int n,m,t;
int sqrt_m;
int c,d[1000][2];
cin>>t;
Init();
while(t--)
{
cin>>n>>m;
c=0;
sqrt_m=(int)sqrt(double(m))+1;//求m的质因子 只需从1遍历到根号m就可以
for(int i=0;i<1000;i++) d[i][1]=0;
for(int i=0;i<size&&b[i]<sqrt_m;i++)
{
if(m%b[i]==0)
{
d[c][0]=b[i];///d[i][0] 存的是m的质因子
while(m%b[i]==0)
{
d[c][1]++;//d[i][1] 存的是m能整除这个质因子的多少次幂
m/=b[i];
}
c++;//m有c个质因子
}
if(m==1) break;//当m==1的时候,已经找出了m的所有的质因子了
}
if(m!=1)
{
d[c][0]=m;
d[c][1]++;
c++;
}
bool flag=true;
int min=0x3f3f3f3f;
int f=0;
for(int i=0;i<c&&flag;i++){
int j=1;
if(n/d[i][0]==0) flag=false;
else
{
f=0;
while(n/d[i][0]>0)
{
int num=(int)pow(double(d[i][0]),double(j));//因为是n!所以求出这个素因数的j次幂
f+=n/num;// 累加n除这个素因数的j次幂的结果 这里可能有人不理解
//举个例子 6!算质因子2的f 第一遍是6/2=3 第二遍是6/4=1 求出f=4
//6/2=3可以想成6的阶乘中2 4 6都能整除2 然后6/4=1 6!中只有4可以整除4
//那么2 4 6 中4可以整除2两次 2 6只能1次
//这个循环求出的就是1~n中能整除这个质因子个数 1~n中能整除这个质因子2次的数的个数。。。以此类推
j++;
if(n/num==0) break;//此时这个素因数的j次幂已经大于n了 所以不需要再累加了
}
if(f<d[i][1]) flag=false;//如果n!中这个素因数的f次幂小于m中这个素因数的d[i][1]次幂那么n!不能整除m了
else f/=d[i][1]; //求出n!中的这个素因数的f次幂是m中这个素因数的d[i][1]的倍数
if(min>f) min=f;//求出最小的倍数
}
}
if(flag) cout<<min<<endl;
else cout<<"-1"<<endl;
}
return 0;
}