[BZOJ3209]花神的数论题 组合数+快速幂

3209: 花神的数论题

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 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

Sample Output

样例输出一

2

HINT

 



对于样例一,1*1*2=2;


数据范围与约定


对于 100% 的数据,N≤10^15

 

Source

原创 Memphis

 

枚举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 }
View Code

 

posted @ 2017-12-26 16:08  wls001  阅读(130)  评论(0编辑  收藏  举报