| | | | 描述 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的余数即可。
| | | |
| | | | 注释 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;
}