bzoj3209 花神的数论题

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

 

正解:数位$dp$。

数位$dp$水题。设$f[i][j][k]$表示前$i$位,二进制和为$j$,当前这位有没有限制的答案。

直接用记忆化搜索转移即可。

 

 1 #include <bits/stdc++.h>
 2 #define il inline
 3 #define RG register
 4 #define ll long long
 5 #define rhl (10000007)
 6 
 7 using namespace std;
 8 
 9 int f[70][70][2],st[70],top;
10 ll n;
11 
12 il int gi(){
13   RG int x=0,q=1; RG char ch=getchar();
14   while ((ch<'0' || ch>'9') && ch!='-') ch=getchar();
15   if (ch=='-') q=-1,ch=getchar();
16   while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar();
17   return q*x;
18 }
19 
20 il int dfs(RG int pos,RG int tot,RG int lim){
21   if (!pos) return tot?tot:1;
22   if (f[pos][tot][lim]!=-1) return f[pos][tot][lim];
23   RG int end=lim?st[pos]:1,&res=f[pos][tot][lim]; res=1;
24   for (RG int i=0;i<=end;++i)
25     res=1LL*res*dfs(pos-1,tot+i,lim && i==end)%rhl;
26   return res;
27 }
28 
29 int main(){
30 #ifndef ONLINE_JUDGE
31   freopen("god.in","r",stdin);
32   freopen("god.out","w",stdout);
33 #endif
34   cin>>n; memset(f,-1,sizeof(f));
35   while (n) st[++top]=n&1,n>>=1;
36   cout<<dfs(top,0,1); return 0;
37 }

 

posted @ 2017-11-01 23:01  wfj_2048  阅读(173)  评论(0编辑  收藏  举报