題目大意:
有一個與階乘有關的遊戲,給出兩個整數n ,m ,令t=n!,每輪遊戲的流程如下
1.如果 m不能整除t ,即 t mod m !=0 ,跳到第三步;如果能整除,跳到第二步
2.令t=t/m,xyx的得分+1並返回第一步
3.遊戲結束
xyx共進行T輪遊戲,他想知道每輪他的得分是多少
特別注意,m,n<10e9;
解題思路:
先理解一下題意,其實就是找n中有多少個m,可以先考慮m是質數的情況,發現在n!中,每隔m個數會出現m的倍數,我們只要不停地/m就好了。
那m是合數怎麼辦? 可以用篩法把m分解質因數,每次記錄當前質因數以及它出現的次數,然後每次算出n中有多少個當前質因數,注意因爲可能一個質因數出現多次,最後需要再/p,最後取最小值就可以了。
#include<cstdio>
#include<iostream>
using namespace std;
int T,n,m;
int ans;
int cal(int p,int a)//求n中有幾a個p
{
int t=0;
for (int i=n;i;i/=p) t+=i/p;
return t/a;
}
main()
{
// freopen("fac.in","r",stdin);
// freopen("fac.out","w",stdout);
cin>>T;
while(T--)
{
scanf("%d%d",&n,&m);
ans=2e9;
for (int t,s,i=2;i*i<=m;++i)
if (m%i==0)
{
t=i;s=0;
while(m%i==0){//篩法分解質因數
s++;
m/=i;
}
ans=min(ans,cal(t,s));
}
if (m>1) ans=min(ans,cal(m,1));//因爲篩法枚舉的是小於等於根號m的質因數,如果分解後m>1,說明有且僅有一個大於根號m的質因數,特判一下。
printf("%d\n",ans);
}
}