码迷,mamicode.com
首页 > 其他好文 > 详细

2017.9.24 noip模拟赛 day2—组合数

时间:2017-09-24 17:21:33      阅读:143      评论:0      收藏:0      [点我收藏+]

标签:题意   范围   day   while   getchar   printf   16px   组合数   nbsp   

简化版题意:

给定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—组合数

标签:题意   范围   day   while   getchar   printf   16px   组合数   nbsp   

原文地址:http://www.cnblogs.com/zeroform/p/7587619.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!