3209: 花神的数论题
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 2498 Solved: 1129
[Submit][Status][Discuss]
Description
背景
众所周知,花神多年来凭借无边的神力狂虐各大 OJ、OI、CF、TC …… 当然也包括 CH 啦。
描述
话说花神这天又来讲课了。课后照例有超级难的神题啦…… 我等蒟蒻又遭殃了。
花神的题目是这样的
设 sum(i) 表示 i 的二进制表示中 1 的个数。给出一个正整数 N ,花神要问你
派(Sum(i)),也就是 sum(1)—sum(N) 的乘积。
Input
一个正整数 N。
Output
一个数,答案模 10000007 的值。
Sample Input
样例输入一
3
3
Sample Output
样例输出一
2
2
HINT
对于样例一,1*1*2=2;
数据范围与约定
对于 100% 的数据,N≤10^15
Source
枚举1的个数,组合数+快速幂即可。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<cmath> 5 #include<cstring> 6 #include<algorithm> 7 #define mod 10000007 8 #define LL long long 9 using namespace std; 10 LL c[65][65]; 11 void pre() { 12 for(int i=0;i<=60;i++) c[i][0]=1; 13 for(int i=1;i<=60;i++) for(int j=1;j<=i;j++) c[i][j]=c[i-1][j]+c[i-1][j-1]; 14 } 15 LL w[100]; 16 LL n,len; 17 LL power(LL a,LL b) { 18 LL ans=1; 19 while(b) { 20 if(b&1) ans*=a,ans%=mod; 21 a*=a;a%=mod; 22 b>>=1; 23 } 24 return ans; 25 } 26 LL cnt(LL x) { 27 LL ans=0; 28 for(int i=len;i>=1;i--) { 29 if(w[i]) ans+=c[i-1][x],x--; 30 if(x<0) break; 31 } 32 return ans; 33 } 34 int main() { 35 pre(); 36 scanf("%lld",&n); 37 n++; 38 while(n) { 39 w[++len]=n&1; 40 n>>=1; 41 } 42 LL ans=1LL; 43 for(int i=1;i<=len;i++) ans*=power(i,cnt(i)),ans%=mod; 44 printf("%lld",ans); 45 }