题目连接
题意:求 Pmn 即 n!m! 中末尾非0 的数字。
思路: 首先我们知道,2和5相乘末尾非0数字为1,可以相互相消。我们先把这两个因子抽离出来,考虑末尾为3,7,9的因子。
定义 f(n,x):n! 因子中,抽离了2,5后末尾数字为 x 的因子的个数。
g(n,x):n! 中所有奇因子末尾数字为 x 的因子的个数。
分析可以知道 f(n,x)=f(n2,x)+g(n,x) ;
可以这样想,对于 n!的每一个因子k,如果k是偶数则除二归到f(n2,x)中,如果k是奇数则到g(n,x) 中,这样就有了上面那条式子。
接下来分析g(n,x),末尾数字共有1、3、5、7、9,1可以忽略,5可以用递归g(n5,x)求,x=3、5、7的话, 共有n10个尾数是x的因子,如果n%10≥x,那么加1,再加上因子中抽离5后的数g(n5,x) 。
所以g(n,x)=n10+(n%10≥x)+g(n5,x) ;
对于2,5的因子个数可以这样求,getx(n,x)=getx(nx,x)+nx(x=2,5);
现在要算的是 n!m! 的结果,因为结果肯定是整数,所以因子个数可以直接相减,
把2,3,5,7,9的数目求出来后,要比较2,5因子个数谁多,2多就要减去5的(相消),相等就两个都不要,5多就要乘以5.
剩下3,7,9因子指数相乘时有个循环节,mod3[4]={1,3,9,7};mod7[4]={1,7,9,3};mod9[4]={1,9,1,9};
看有多少个因子数直接可以得出 cnt个x 的因子相乘的末尾数。
#include <iostream>
#include <cmath>
#include <stdio.h>
#include <map>
#include <string>
#include <string.h>
#include <algorithm>
#include <queue>
using namespace std;
#define REP(i,a,b) for(int i=a;i<b;++i)
#define scan(a) scanf("%d",&a)
#define maxn 500005
#define mset(a,b) memset(a,b,sizeof a)
#define LL long long
int g(int n,int x)
{
if(!n) return 0;
return n/10+(n%10>=x)+g(n/5,x);
}
int f(int n,int x)
{
if(n==0) return 0;
return f(n/2,x)+g(n,x);
}
int getx(int n,int x)
{
if(n<x) return 0;
return n/x+getx(n/x,x);
}
int mod2[4]={6,2,4,8};
int mod3[4]={1,3,9,7};
int mod7[4]={1,7,9,3};
int mod9[4]={1,9,1,9};
int main()
{
int n,m;
int cnt[10];
while(cin>>n>>m)
{
m=n-m;
cnt[2]=getx(n,2)-getx(m,2);
cnt[3]=f(n,3)-f(m,3);
cnt[5]=getx(n,5)-getx(m,5);
cnt[7]=f(n,7)-f(m,7);
cnt[9]=f(n,9)-f(m,9);
//cnt[2]-=cnt[5];
int ans=1;
if(cnt[2]>cnt[5])
ans*=mod2[(cnt[2]-cnt[5])%4];
else if(cnt[2]==cnt[5]) ;
else ans*=5;
ans*=mod3[cnt[3]%4];
//ans*=mod5[cnt[5]%4];
ans*=mod7[cnt[7]%4];
ans*=mod9[cnt[9]%4];
ans%=10;
cout<<ans<<endl;
}
}