题目链接:点击打开链接
题目的意思很是简单:
n!在b进制下,末尾0为为k个的b有多少个。
先把n!的分解质因数。不需要全部的分解。因为n/k < 500。
比如说数据n=10,k=2;
10!=2^8*3^4*5^2*7=(2^4*3^2*5)^2*7;
那么末尾为2个的0的就靠(2^4*3^2*5)来进行组合了。
2^0---2^4;
3^0---3^2;
5^0---5^1;所有的组合就是5*4*2=30种。
我们知道里面一定有一些不符合的。
那么不符合是那些呢?
2^0---2^2
3^0---3^1
5^0;
是不符合。为什么?
因为2^8/2^0=2^7这样的话,就是末尾有7个0了。
其他同理。
那么不符合条件的就是,3*2*1=6种了。
答案:30-6=24;
代码:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
#define LL __int64
const int N=505;
const LL mod=1e9+7;
int prime[N],top;
bool Judge(int x){
int i,d=(int)sqrt(x);
for(i=2;i<=d&&x%i!=0;i++);
if(i>d) return true;
else return false;
}
void get_prime(){
int i;top=0;
for(i=2;i<=500;i++){
if(Judge(i))
prime[top++]=i;
}
top=top-1;
}
LL f(LL n,LL m){
if(n<m) return 0;
else return n/m+f(n/m,m);
}
int main(){
get_prime();
LL n,k,T;
scanf("%I64d",&T);
while(T--&&scanf("%I64d%I64d",&n,&k)){
int i;
LL num1[N],ans1=1,ans2=1;
memset(num1,0,sizeof(num1));
for(i=0;i<=top;i++){
num1[i]=f(n,prime[i]);
}
for(int i=0;i<=top;i++){
if(num1[i]/k){
int d=num1[i]/k,d1=0;
ans1=(ans1*(d+1))%mod;
for(int j=1;j<=d;j++)
if(num1[i]/j!=k) d1++;
else break;
ans2=(ans2*(d1+1))%mod;
}
}
printf("%I64d\n",((ans1-ans2)%mod+mod)%mod);
}
return 0;
}
最后一段:
((ans1-an2)%mod+mod)%mod;
在许多程序中,都看到过这一句话。
今天终于知道为什么咯!
因为ans1,和ans2都是mod后的,就是有可能ans1<ans2。所以要这么处理一下。