当前位置: 代码迷 >> 综合 >> POJ【数学】1150 The Last Non-zero Digit
  详细解决方案

POJ【数学】1150 The Last Non-zero Digit

热度:38   发布时间:2023-11-21 06:59:39.0

POJ 1150 The Last Non-zero Digit

(这题怎么跑到组合数学里面来了???)

题目大意

◆题目传送门◇

N!(N?M)!\frac{N!}{(N-M)!}(N?M)!N!?的最后一位非零数字。

分析

我们可以将所有的因数101010去掉,问题就转换为了求这个数的最后一位。

但直接去掉因数101010有点麻烦,我们稍退一步,可以先去掉2a×5b2^a\times 5^b2a×5b

这个问题等价于当n!=apen!=ap^en!=apeaaa无法被ppp整除)时,求解eee

一个显然的结论是e=n/p+n/p2+n/p3+…e=n/p+n/p^2+n/p^3+\dotse=n/p+n/p2+n/p3+。(具体可参考《挑战程序设计竞赛(第二版)》293-294页)

我们进一步可以发现,当b>ab>ab>a时,答案一定是555

接下来讨论b≤ab\le aba的情况:

我们现在只需要知道3,7,93,7,93,7,9的个数就可以获得答案。因为3,7,93,7,93,7,9的末尾都是以444为周期出现。

为了求解方便,我们直接讨论n!n!n!

我们将1,2,3,…,N1,2,3,\ldots,N1,2,3,,N分为两个序列:2,4,6…2,4,6\ldots2,4,61,3,5,…1,3,5,\ldots1,3,5,,即偶数序列和奇数序列。

对于偶数序列,我们只需将它除222即可递归转化为奇数序列。对于奇数序列,我们可以发现,每101010个数字中就有3,7,93,7,93,7,9各一,但又因为其中有555的倍数,所以继续除555递归。

至此我们得到了所有的因数2,5,3,7,92,5,3,7,92,5,3,7,9的个数。其中2,52,52,5可以对消为2a?b2^{a-b}2a?b,我们就可以利用这些数的NNN次方尾数是444个一循环即可。

参考代码

#include<cstdio>
#include<algorithm>
using namespace std;const int T[][4]={
    {
    6,2,4,8},//2^4,2^1,2^2,2^3{
    1,3,9,7},//3^4,3^1,3^2,3^3{
    1,7,9,3},//7^4,7^1,7^2,7^3{
    1,9,1,9},//9^4,9^1,9^2,9^3
};int N,M;int Calc(int num,int t) {
    return num==0?0:(num/t+Calc(num/t,t));
}int g(int num,int t) {
    return (num==0)?0:(num/10+(num%10>=t)+g(num/5,t));
}
int cal(int num,int t) {
    return num==0?0:(cal(num/2,t)+g(num,t));
}int main() {
    #ifdef LOACLfreopen("in.txt","r",stdin);freopen("out.txt","w",stdout);#endifwhile(scanf("%d %d",&N,&M)!=EOF) {
    int num2=Calc(N,2)-Calc(N-M,2);int num5=Calc(N,5)-Calc(N-M,5);if(num5>num2) {
    puts("5");continue;} else {
    int ans=1;int num3=cal(N,3)-cal(N-M,3);int num7=cal(N,7)-cal(N-M,7);int num9=cal(N,9)-cal(N-M,9);if(num2>num5)ans*=T[0][(num2-num5)%4],ans%=10;ans*=T[1][num3%4],ans%=10;ans*=T[2][num7%4],ans%=10;ans*=T[3][num9%4],ans%=10;printf("%d\n",ans);}}return 0;
}