poj 1150

原创 2015年07月07日 10:32:53

求最后一个非0位

题目描述:

超大组合数:求超大组合数P(n, m)的最后一个非零位。

题解:

n!/m!的最后一位.可以看出来有几个2和几个5,搞出来有几个10.然后再除以他们之后%10.发现阶乘直接%10不行,因为10是质合数.因此可能这样做:先拆成%5和%2但是发现除以10的x次方之后的数字不好写成形式.于是换这样的方法:只需要是个位,因此只看个位:先看2和5的多少.如果5多于2,一定是5.如果2等于5.那么剩下的就是全部刨去2和5之后剩下的个位数.剩下的3,7,9看结尾的有几个就好了.而如果2多于5,那么结果乘以2就好.之后就是具体怎么算个位的数.对于n,先看奇数,偶数不能处理,因此递归到之后n/2.奇数中的5的倍数,不能处理,因此递归到处理奇数的n/5.

重点:

首先是思路:除去5和2的个位数的统计.
其次是统计:首先递归处理n.然后对n分奇偶.之后对于奇数,在对5进行一次递归

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <ctype.h>
#include <limits.h>
#include <cstdlib>
#include <algorithm>
#include <vector>
#include <queue>
#include <map>
#include <stack>
#include <set>
#include <bitset>
#define CLR(a) memset(a, 0, sizeof(a))
#define REP(i, a, b) for(int i = a;i < b;i++)
#define REP_D(i, a, b) for(int i = a;i <= b;i++)

typedef long long ll;

using namespace std;

int n, m;
int cal_odd(int n, int a)//计算奇数.
{
    if(n==0)
    {
        return 0;
    }
    int ans = 0;
    ans = n/10;
    int t = n%10;
    if(t >= a)
    {
        ans++;
    }
    ans += cal_odd(n/5, a);//重点.计算奇数5.那么递归计算奇数5
    return ans;
}
int cal_n(int n, int a)
{
    if(n==0)
    {
        return 0;
    }
    int ans;
    ans = cal_n(n/2, a) + cal_odd(n, a);//递归
    return ans;
}
int cal_n_2_5(int n, int a)//正常统计
{
    int res = 0;
    while(n!=0)
    {
        res += n/a;
        n /= a;
    }
    return res;
}

int mod(int x, int m)
{
    return (x-1)%m + 1;
}

void solve()
{
    int e3, e7, e9;
    int e5 = cal_n_2_5(n, 5)-cal_n_2_5(m,5),e2=cal_n_2_5(n, 2)-cal_n_2_5(m,2);
    if(e5 > e2)
    {
        printf("5\n");
    }
    else
    {
        e3 = cal_n(n, 3)-cal_n(m, 3);
        e7 = cal_n(n, 7)-cal_n(m, 7);
        e9 = cal_n(n, 9)-cal_n(m, 9);
        e3 = mod(e3, 4);
        e7 = mod(e7, 4);
        e9 = mod(e9, 2);
        int res = 1;
        while(e3!=0)
        {
            res *= 3;
            e3--;
        }
        res %= 10;
        while(e7!=0)
        {
            res *= 7;
            e7--;
        }
        res %= 10;
        while(e9!=0)
        {
            res *= 9;
            e9--;
        }
        res %= 10;
        if(e2 > e5)
        {
            e2 -= e5;
            e2 = (e2 - 1)%4 + 1;
            //e2 %= 4;
            while(e2!=0)
            {
                res *= 2;
                e2--;
            }
        }
        res %= 10;
        printf("%d\n", res%10);
    }
}

int main()
{
    //freopen("1Ain.txt", "r", stdin);
    //freopen("1Aout.txt", "w", stdout);
    while(scanf("%d%d", &n, &m) != EOF)
    {
        m = n - m;
        solve();
    }
    return 0;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

poj 1150 The Last Non-zero Digit

The Last Non-zero DigitTime Limit: 1000MS Memory Limit: 65536KTotal Submissions: 3137 Accepted: 840D...

POJ-1325 && HDU-1150 Machine Schedule 二分图匹配

#include #include #include #include #include #include #include using namespace std; int map[1...

阶乘浅析poj1150 3406 zoj1222 2358

原地址;http://blog.csdn.net/shiwei408/article/details/8739433 阶乘问题分为几类: 1.求阶乘末尾0的个数,,直接除以5,累加即可。 ...

二分图水题整理 Poj 2060 + 1466 + 2771 + hdu 1150 + 1151

Poj 2060 Taxi Cab Scheme 题意:在一个矩形城市里面,有间出租车公司收到翌日的预订行程M个,每个给出起点、终点坐标,两个地点之间的车程就是那两个点之间的曼哈顿距离,...

POJ 1150 The Last Non-zero Digit

The first program Consider the number N! factored into product of powers of prime numbers. It means...

POJ 1150 The Last Non-zero Digit

题意: 求排列数 NPM 最后一个非零位上的数字是多少。NPM 即为 P(N,M) = N!/(N-M)! 解题分析: 很明显,这是道数论题,直接计算是行不通的。对于n!,我们可以写成质因子相乘的形式...

LA-2523 & POJ-1325 & HDOJ-1150 Machine Schedule 解题报告

二分图求最小点集覆盖题。题意:

排列数最后非零位:poj 1150 The Last Non-zero Digit

数论 组合数学(好题)题目大意: 求排列数A(n,m)最后的非零数位解题思路: 参考英文文献,多读几遍,豁然开朗,分析见功底。 http://www.cppblog.com/abilityta...

POJ 1150 The Last Non-zero Digit 阶乘最后非0位

转自:http://www.cppblog.com/abilitytao/archive/2009/10/31/99907.html 这个题怎么来做呢?先别急,我们先来讨论一下下面几个子问题: ...
  • Tsaid
  • Tsaid
  • 2012-02-16 20:11
  • 1533
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)