2017.9.24 noip模拟赛 day2—组合数

Posted Excim

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2017.9.24 noip模拟赛 day2—组合数相关的知识,希望对你有一定的参考价值。

简化版题意:

给定n,m(n<=m),求C(n,m)的末尾有几个0

 

输入格式:

第一行一个整数t,代表数据组数。

接下来t行,每行两个整数n,m

 

输出格式:

t行,每行一个整数,代表C(n,m)的末尾0的个数。

 

样例输入:

 

 

 

3
10 1
11 7
20 4

样例输出:

 

1
1
0

 

数据范围:

1<=m<=n<=1000000,t<=1000

首先这道题需要知道一个公式:C(n,m)=n!/(n-m)!*m!

然后10=2*5,也就是说,对于一个数,我们将其因数分解,2和5中较少的数的个数,就是该数末尾0的个数。

于是对于每一组数据,暴力算出上下两式中2和5的个数,然后上下因为是除的关系,所以可以相互抵消,于是上下的数中2的个数和5的个数中较少的就是0的个数了。

吐槽一句:题解中说,要用前缀和,但是我并没有写任何与前缀和相关的代码,但是还是A了。

再加一句:对于一个数的阶乘,2的个数一定是比5多的,所以这个题其实只需要输出5的个数就好了。。。比较大小只是保险而已。

 

#include<cstdio>
void read(int &y)
{
    y=0;char x=getchar();
    while(x<0||x>9) x=getchar();
    while(x>=0&&x<=9)
    {
        y=y*10+x-0;
        x=getchar();
    }
}
int solve2(int x)
{
    int s=0;
    while(x/2!=0)
    {
        s+=x/2;
        x/=2;
    }
    return s;
}
int solve5(int x)
{
    int s=0;
    while(x/5!=0)
    {
        s+=x/5;
        x/=5;
    }
    return s;
}
int min(int x,int y)
{
    return x<y ? x : y;
}
int t,m,n;
int main()
{
    read(t);
    while(t--)
    {
        read(m),read(n);
        int x=solve2(m)-(solve2(n)+solve2(m-n));
        int y=solve5(m)-(solve5(n)+solve5(m-n));
        printf("%d\n",min(x,y));
    }
    return 0;
}

 

以上是关于2017.9.24 noip模拟赛 day2—组合数的主要内容,如果未能解决你的问题,请参考以下文章

$NOIP 2018 Day2$ 模拟考试 题解报告

NOIP 2016 day2

Noip2016day2 组合数问题problem

NOIP2016提高组 Day2 T1 组合数问题

计蒜客NOIP2017提高组模拟赛day2-小区划分

2016.10.30 NOIP模拟赛 day2 AM 整理