poj 1150 The Last Non-zero Digit

Posted ZefengYao

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了poj 1150 The Last Non-zero Digit相关的知识,希望对你有一定的参考价值。

The Last Non-zero Digit
Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 5363   Accepted: 1642

Description

In this problem you will be given two decimal integer number N, M. You will have to find the last non-zero digit of the NPM.This means no of permutations of N things taking M at a time.

Input

The input contains several lines of input. Each line of the input file contains two integers N (0 <= N<= 20000000), M (0 <= M <= N).

Output

For each line of the input you should output a single digit, which is the last non-zero digit of NPM. For example, if NPM is 720 then the last non-zero digit is 2. So in this case your output should be 2.

Sample Input

10 10
10 5
25 6

Sample Output8

4
2

题意:求A(n,m)的最后一个非零末尾,A(n,m)即n!/(n-m)!
思路:先把A(n,m)中的所有2和5因子提取出来,考虑剩余部分的积的末尾,这可以表示为A(n,m)/(2^a*5^b)
,其中a,b为2,5的因子个数,那么剩余部分的因子结尾一定为3,7,9,可以先把这部分的乘积的末尾求出来(3,7,9的n次方的末尾数都是4个1循环,方便求得),之后再结合因子2和5,若5的个数多于2,最终结尾一定为5,若2的个数多于5,多出来的2^(a-b)
末尾也是4个数一循环,可以方便求出来。

那么现在的关键是如何求得因子结尾是3,7,9的那些数的个数,我么可以将n!分成两个数列,奇数列和偶数列,先看奇数列,奇数列中每间隔10都会出现一个3,7,9的数,最后间隔小于10的部分则考虑剩余部分间隔是否大于x(3,7,9),若x大于间隔,则存在一个以x结尾的因子.考虑到数列中有5的倍数,n/5递归数列继续以上的操作。
偶数列不断递归除以2也能得到奇数列。
AC代码:


#define _CRT_SECURE_NO_DEPRECATE
#include<iostream>
#include<cstdio>
#include<vector>
#include<algorithm>
#include<cstring>
#include<set>
#include<string>
#include<queue>
#include<cmath>
using namespace std;
#define INF 0x3f3f3f3f
const int N_MAX = 20000000+4;
int n,m;
//计算n!中x的因子个数
int prime_num(int n, int x) {
    int num = 0;
    while(n) {
        num += n / x;
        n /= x;
    }
    return num;
}
//计算n!以3,7,9结尾的因子的个数
int odd_end_with(int n,int x) {
    if (n == 0)return 0;
    return n / 10 +((n%10)>=x)+odd_end_with(n / 5, x) ;
}
int end_with(int n,int x) {
    if (n == 0)return 0;
    return odd_end_with(n,x) + end_with(n/2,x);
}
int table[4][4] = {
  6, 2, 4, 8,//2
  1, 3, 9, 7,//3
  1, 7, 9, 3,//7
  1, 9, 1, 9//9
};


int main() {
    while (scanf("%d%d",&n,&m)!=EOF) {
        int two = prime_num(n, 2) - prime_num(n - m, 2);
        int five = prime_num(n, 5) - prime_num(n - m, 5);
        if (five > two) { printf("5\n"); continue; }

        int three = end_with(n, 3) - end_with(n - m, 3);
        int seven = end_with(n, 7) - end_with(n - m, 7);
        int nine = end_with(n, 9) - end_with(n - m, 9);
        int res = 1;
        if(two>five)res *= table[0][(two - five) % 4];
        res *= table[1][three % 4];
        res *= table[2][seven % 4];
        res *= table[3][nine % 4];
        res %= 10;
        printf("%d\n",res);
    }
    return 0;
}

 

以上是关于poj 1150 The Last Non-zero Digit的主要内容,如果未能解决你的问题,请参考以下文章

1150 Travelling Salesman Problem (25 分)

PAT甲级——A1150 TravellingSalesmanProblem25

PAT 甲级 1150 Travelling Salesman Problem

poj 2720 Last Digits

poj 2720 Last Digits

The last packet successfully received from the server was 20,519 milliseconds ago. The last packet