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了。

 

#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;
}

 

posted @ 2017-09-24 16:55  Excim  阅读(182)  评论(0编辑  收藏  举报