POJ 1150-The Last Non-zero Digit(求阶乘最后一位非零数)

The Last Non-zero Digit

Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%I64d
& %I64u

Submit Status Practice POJ
1150

Appoint description: 
System Crawler  (2015-03-30)

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 NM.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 NM. For example, if NM 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 Output

8
4
2

题意:求C(n,m)的最后一位非零数。

思路:弱刚开始搞数学,这些入门题就已经搞的死死的,参考的巨巨的思路和代码,Orz,附链接求阶乘最后一位非零数

相当于求n!/(n-m)!的最后一位非零数,首先先得明白n!的最后一位非零数怎么求,例如对10!:

step1:首先将10!中所有2,5因子去掉;

step2:然后求出剩下的一串数字相乘后末尾的那个数。 (重点)

step3:由于去掉的2比5多,最后还要考虑多余的那部分2对结果的影响。

step4:output your answer!

#include <stdio.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
#include <sstream>
#include <algorithm>
#include <set>
#include <queue>
#include <stack>
#include <map>
using namespace std;
typedef long long LL;
const int inf=0x3f3f3f3f;
const double pi= acos(-1.0);
int get_2(int x)//计算阶乘中质因子2的出现次数
{
    if(x==0)
        return 0;
    else
        return (x/2+get_2(x/2));
}
int get_5(int x)//计算阶乘中质因子5的出现次数
{
    if(x==0)
        return 0;
    else
        return (x/5+get_5(x/5));
}
int get(int n,int x)//计算f(1) to f(n) 中,奇数数列中末尾为x的数出现的次数
{
    if(n==0)
        return 0;
    else
        return (n/10+(n%10>=x)+get(n/5,x));
}
int get_f(int n,int x)//计算f(1) to f(n)中,末尾为x的数的出现次数

{
    if(n==0)
        return 0;
    return get_f(n/2,x)+get(n,x);
}
int mp[4][4]={
{6,2,4,8},//2^n%10的循环节,注意如果2的个数为0时候,结果应该是1,要特殊处理。
{1,3,9,7},//3
{1,7,9,3},//7
{1,9,1,9}//9
};//3,7,9的循环节中第一位,刚好是1,故不需要考虑这些数字出现次数为0的情况。
int main()
{
    int n,m;
    int res;
    while(~scanf("%d %d",&n,&m)){
        int n2=get_2(n)-get_2(n-m);
        int n5=get_5(n)-get_5(n-m);
        int n3=get_f(n,3)-get_f(n-m,3);
        int n7=get_f(n,7)-get_f(n-m,7);
        int n9=get_f(n,9)-get_f(n-m,9);
        res=1;
        if(n5>n2){
            printf("5\n");
        }
        else{
            if(n2!=n5){
                res*=mp[0][(n2-n5)%4];
                res%=10;
            }
            //如果num2==num5,那么2^0次方mod 10应该为1 ,而不是table中的6,所以要特殊处理。
                res*=mp[1][n3%4];
                res%=10;
                res*=mp[2][n7%4];
                res%=10;
                res*=mp[3][n9%4];
                res%=10;
            printf("%d\n",res);
        }
    }
    return 0;
}
时间: 2024-08-04 16:37:29

POJ 1150-The Last Non-zero Digit(求阶乘最后一位非零数)的相关文章

(hdu step 2.3.7)Last non-zero Digit in N!(阶乘最后一位非零位)

在写题解之前给自己打一下广告哈~..抱歉了,希望大家多多支持我在CSDN的视频课程,地址如下: http://edu.csdn.net/course/detail/209 题目: Last non-zero Digit in N! Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 815 Accepted Submission(s): 344

【GDOI 2011 DAY2 T3】零什么的最讨厌了 (快速求阶乘、中国剩余定理)

问题描述: 林记在做数学习题的时候,经常遇到这种情况:苦思冥想了很久终于把问题解出来,结果发现答案是0,久而久之林记在得到习题答案是0的时候就没有了做出一道难题的成就感.于是林记决定:以后出题,答案一定不能是0,例如求n!最低位非零数这样的习题就很不错了. 现在林记提出了一个更难一点的问题:求n!在K进制下的最低位非零数.其中K符合一些特殊的条件:K是由若干个互不相同的质数相乘得出来的,例如K=2,3,5,6,7,10…… 输入格式: 首先输入的第一行是一个整数Q,表示询问的个数. 接下来是Q个

POJ 1150 The Last Non-zero Digit 数论+容斥

POJ 1150 The Last Non-zero Digit 数论+容斥 题目地址: POJ 1150 题意: 求排列P(n, m)后面第一个非0的数. 分析: 为了熟悉题目中的理论,我先做了俩初级的题目: POJ 1401,题解见:POJ 1401 && ZOJ 2202 Factorial 阶乘N!的末尾零的个数 NYOJ 954,题解见:NYOJ 954 求N!二进制末尾几个0 这题想了一下,十进制末尾几个0可以转化为几个5因子,二进制最后一位非0可以转化为2因子,但是10进制就

poj 1150 The Last Non-zero Digit

1 /** 2 大意: 求A(n,m)的结果中从左到右第一个非零数 3 思路: 0是由2*5的得到的,所以将n!中的2,5约掉可得(2的数目比5多,最后再考虑进去即可) 4 那n!中2 的个数怎么求呢? 5 int get2(int n){ 6 if(n==0) 7 return 0; 8 return n/2+get2(n/2); 9 } 10 eg: 1*2*3*4*5*6*7*8*9*10 约去2,5可得,,1*1*3*1*1*3*7*1*9*1 11 所以最后肯定是3,7,9..的数列,

#数论-模运算#POJ 1150、1284、2115

1.POJ 1150 The Last Non-zero Digit #质因数分解+模运算分治# 先贴两份题解: http://www.hankcs.com/program/algorithm/poj-1150-the-last-non-zero-digit.html http://www.cppblog.com/abilitytao/archive/2009/10/31/99907.html 下面是自己看完题解(划掉)之后的理解: 题目要求出组合数Anm=n!/(n-m)!(说实话一开始不知道

poj 2478 Farey Sequence(基于素数筛法求欧拉函数)

http://poj.org/problem?id=2478 求欧拉函数的模板. 初涉欧拉函数,先学一学它基本的性质. 1.欧拉函数是求小于n且和n互质(包括1)的正整数的个数.记为φ(n). 2.欧拉定理:若a与n互质,那么有a^φ(n) ≡ 1(mod n),经常用于求幂的模. 3.若p是一个质数,那么φ(p) = p-1,注意φ(1) = 1. 4.欧拉函数是积性函数: 若m与n互质,那么φ(nm) = φ(n) * φ(m). 若n = p^k且p为质数,那么φ(n) = p^k - p

POJ 3047 Bovine Birthday 给出年月日求星期 蔡勒公式

题目来源:POJ 3047 Bovine Birthday 题意:... 思路:蔡勒公式 适合于1582年(中国明朝万历十年)10月15日之后的情形 公式 w = y + y/4 + c/4 - 2*c + 26 * (m+1)/10 + d - 1; m如果是1 2 月份 y要倒退1年 m += 12 y是年份的后两位 y = year%100 c是世纪 c = year/100 #include <cstdio> #include <cstring> using namespa

POJ 2750 Potted Flower (单点修改求线段树上最大子序列和)

题目大意: 在一个序列上每次修改一个值,然后求出它的最大的子序列和. 思路分析: 首先我们不考虑不成环的问题.那就是直接求每个区间的最大值就好了. 但是此处成环,那么看一下下面样例. 5 1 -2 -3 4 5 那么你会发现 max = sum - min 也就是和减去最小区间和也可以得到. 所以我们最后要得到的就是两个东西.注意题目中说的不能全部取得.所以还要判断一下max 是不是等于 sum的. #include <cstdio> #include <iostream> #in

POJ 1845 Sumdiv【同余模运算+递归求等比数列和+快速幂运算】

快速幂运算在第一次训练时候就已经遇到过,这里不赘述 同余模运算也很简单,这里也不说了,无非是(a+b)%m (a*b)%m 把m弄到里面变成(a%m+b%m)%m   (a%m*b%m)%m 今天学的最重要的还是递归二分求等比数列 题目大意是给出A和B,求A^B的约数和 解这个题,首先,对A进行素因子分解得到 (PI(pi^ai))^B 然后我们有约数和公式: 对A=PI(p1^k1) A的所有因子之和为S = (1+p1+p1^2+p1^3+...p1^k1) * (1+p2+p2^2+p2^