哈理工OJ 1037组合数末尾的零(思维)

本文探讨了从m个不同元素中取出n个元素的所有组合数C(m, n)转换为二进制数后末尾零的数量计算方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

组合数末尾的零
Time Limit: 1000 MSMemory Limit: 65536 K
Total Submit: 250(168 users)Total Accepted: 163(145 users)Rating: Special Judge: No
Description

m个不同元素中取出(≤ m)个元素的所有组合的个数,叫做从m个不同元素中取出n个元素的组合数。组合数的计算公式如下:

C(mn) = m!/((n)!n!)

 

现在请问,如果将组合数C(mn)写成二进制数,请问转这个二进制数末尾有多少个零。

Input

第一行是测试样例的个数T,接下来是T个测试样例,每个测试样例占一行,有两个数,依次是mn,其中≤ 1000。

Output

分别输出每一个组合数转换成二进制数后末尾零的数量。

Sample Input

2

4 2

1000 500

Sample Output

1

6


看到数据范围1000,第一想法是大数,第二想法是蛋疼的找规律。最后还是看了大牛的代码我才得以超生。。

这里思路定型之后就很简单了,我们知道,除法中0的个数的计算是可以用减法来计算的,所以我们只需要计算各个数的0的个数就行了(当然是二进制下的)一共这里要求三个数的二进制数的0的个数(当然是末尾了):分别是m,m-n,n;

然后进行减法计算就行了,那么我们如何计算二进制数末尾的0的个数呢?这里我们直接来举例说明,比如现在给出十进制数5;

我们来把他按照进制转换的规则把他换成2进制的数:

5/2=2...1

2/2=1....0

那么这里二进制数就是101,那么如果我在5上边乘个2呢?

这里就变成了这样:

10/2=5...0

5/2=2...1

2/2=1....0

然后结果就变成了1010,我们发现,如果再乘个2的话,就又多了个0(二进制的末尾,童鞋可以试一试20的二进制数,一定是10100)

有了这个特性,我们就能得出结论,并且写出代码:如果阶乘的过程中乘一个2,那么二进制的末尾就多个0:相反的,童鞋们也可以试一试乘个3,他的末尾是不会多出0的情况的。然后知道了这个特性,我们就直接写出代码:

/*函数功能:计算每个数变成二进制之后0的个数.*/

#include<stdio.h>
#include<string.h>
#include<iostream>
using namespace std;
int jisuan(int n)
{
    int num,sum=0;
    for(int i=1;i<=n;i++)
    {
        int x=i;
        num=0;
        while(x!=0)
        {
            if(x%2==1)
            break;
            else
            {
                num++;
                x/=2;
            }
        }
        sum+=num;
    }
    return sum;
}
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        int m,n;
        cin>>m>>n;
        cout<<jisuan(m)-jisuan(m-n)-jisuan(n)<<endl;
    }
}










评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值