题意:求n!/(n-m)!的最后一位非零位。
题解:直接求结果模10会超时,而且2和5的结果必然是0,所以先把n!中2和5的因子去掉。
可以看出:1,2,3,4,5,6,7,8,9,10。。。除尽2和5之后为1,1,3,1,1,3,7,1,9,1。。。只剩下1,3,7,9的结尾的数。我们只需要统计一下以3,7,9结尾的数字个数即可。若干个3相乘结果的结尾是有规律的,可以简化计算。写两个函数统计以3,7,9结尾的个数,
我们求1,2,3,4,5,6,7,8,9,10结尾3,7,9个数发现,1,2,3,4,5,和2,4,6,8,10个数是一样的,所以我们需统计一下f(n/2)+g(n)即可。
因为5,15,25,35除以若干个5后结果是1,3,1,7,9,1,3,1,7,9...于是在加上g(n/5),即可。
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <string.h>
using namespace std;
int fact_prime(int n, int x)
{
int res = 0;
while (n)
{
res += n / x;
n /= x;
}
return res;
}
int g(int n,int x)
{
if(n==0) 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 a[4][4]={
6, 2, 4, 8,
1, 3, 9, 7,
1, 7, 9, 3,
1, 9, 1, 9,
};
int main()
{
int n,m;
while(scanf("%d%d",&n,&m)!=EOF)
{
m=n-m;
int tow=fact_prime(n,2)-fact_prime(m,2);
int five=fact_prime(n,5)-fact_prime(m,5);
int three=f(n,3)-f(m,3);
int seven=f(n,7)-f(m,7);
int nine=f(n,9)-f(m,9);
if(tow<five)
{
printf("%d\n",5);
}
else
{
int res=1;
if(tow-five!=0)
res*=a[0][(tow-five)%4];
res *= a[1][three % 4];
res *= a[2][seven % 4];
res *= a[3][nine % 4];
res %= 10;
printf("%d\n", res);
}
}
return 0;
}