tyvj 1318 comb 在组合数C(n,0),C(n,1),……,C(n,n-1),C(n,n)中,有多少个奇数。

该博客讨论了如何确定组合数C(n,k)中奇数项的数量。当n和k按位与运算结果等于k时,C(n,k)为奇数。通过计算n、n-k以及n的二进制表示中1的个数,可以判断奇数项的个数。博主给出了一个使用二进制转换和数学计算的解决方案,并提供了C++代码实现。" 112633638,10537673,理解与实现:1位全加器的组合逻辑电路,"['数字电路', '逻辑门', '电路仿真', '电子工程', '组合逻辑']

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

 
From lwz_th
comb
 
   
   
 描述 Description  
  Will最近最近很磋很磋,很2很2(但是Will绝不23)……于是Will也不知道怎么就遇到了一个问题,并且Will很想让人帮他做出来。问题是这样的:在组合数C(n,0),C(n,1),……,C(n,n-1),C(n,n)中,有多少个奇数。
例如:当n=2时,C(2,0)=1,C(2,1)=2,C(2,2)=1;故总共有2个奇数。

   
   
 输入格式 Input Format 
  输入文件有若干行,每行为一组测试数据,其中包含一个整数。

   
   
 输出格式 Output Format 
  输出文件为。
对于每组输入,给出一个答案。
每个答案占一行,答案可能很大,你只需要输出其mod 22222223的余数即可。

   
   
 样例输入 Sample Input  
 
   
   
 样例输出 Sample Output  
 
   
   
 时间限制 Time Limitation 
  1S
   
   
 注释 Hint 
  30%的数据中N≤20;
100%的数据中N≤10^300。

对于100%的数据,每组数据不超过100行。

 

 

对于C(n,k),若n&k == k 则c(n,k)为奇数,否则为偶数

n!中含有2因子的个数等于(n-它的二进制形式中1的个数)(每除一次如果有1的话去掉一个1)。那么题意再次转化为求m,n-m以及n的二进制形式中1的个数。或者说,看n&m ?= m,这个呢,如果等于,那么也就意味着,所有m中为1的位置n一定为1,那么n-m就可以直接用二进制减,这样得到的差的二进制中1的个数加上m中二进制1的位数正好等于n中1的位数,由前面可以知道,这就是一个奇数

 

这样共有2^t次方中情况(t表示n的二进制中1的个数)

 

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define __int64 long long
const __int64 md=22222223;
const __int64 maxn=2000;
__int64 t[maxn],A[maxn];
//{ 0-9,A-Z,a-z } 62中符号
void change(__int64 a,__int64 b,char *s,char *d)//s在a进制下,转换成b进制,保存到d中
{
    int i,k,l;
    for(k=i=strlen(s);0<i--;)
                     t[k-1-i]=s[i]-(s[i]<58?48:s[i]<97?55:61);
            for(l=0;k;)
            {
                     for(i=k;1<i--;)
                     {
                               t[i-1]+=t[i]%b*a;
                               t[i]/=b;
                     }
                     A[l++]=t[0]%b;
                     t[0]/=b;
                     for(;0<k&&!t[k-1];k--);
            }
            for(d[l]=i=0;i<l;i++)
                     d[l-1-i]=A[i]+(A[i]<10?48:A[i]<36?55:61);
}
__int64 _pow(__int64 a,__int64 b,__int64 md)
{
    if(b==0) return 1;
    if(b==1) return a%md;
    __int64 cnt=_pow(a,b/2,md);
    cnt=cnt*cnt%md;
    if(b&1) cnt=cnt*a%md;
    return cnt;
}
int main()
{
   // freopen("out.txt","w",stdout);
    char s[maxn];
    while(gets(s))
    {
        char d[maxn]="";
        change(10,2,s,d);
        __int64 t=0;
        int len=strlen(d);
        for(int i=0;i<len;i++) t+=d[i]=='1';
        __int64 cnt=_pow(2,t,md);
        cout<<cnt<<endl;
    }
    return 0;
}

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值