背景
众所周知,花神多年来凭借无边的神力狂虐各大 OJ、OI、CF、TC …… 当然也包括 CH 啦。
描述
话说花神这天又来讲课了。课后照例有超级难的神题啦…… 我等蒟蒻又遭殃了。
花神的题目是这样的
设 sum(i) 表示 i 的二进制表示中 1 的个数。给出一个正整数 N ,花神要问你
派(Sum(i)),也就是 sum(1)—sum(N) 的乘积。
标签:
题目连接:http://www.lydsy.com/JudgeOnline/problem.php?id=3209
背景
众所周知,花神多年来凭借无边的神力狂虐各大 OJ、OI、CF、TC …… 当然也包括 CH 啦。
描述
话说花神这天又来讲课了。课后照例有超级难的神题啦…… 我等蒟蒻又遭殃了。
花神的题目是这样的
设 sum(i) 表示 i 的二进制表示中 1 的个数。给出一个正整数 N ,花神要问你
派(Sum(i)),也就是 sum(1)—sum(N) 的乘积。
一个正整数 N。
一个数,答案模 10000007 的值。
Hint
对于样例一,1*1*2=2;
数据范围与约定
对于 100% 的数据,N≤10^15
#include<iostream> #include<cstdio> #include<cstring> #include<string> #include<queue> #include<set> #include<vector> #include<map> #include<stack> #include<cmath> #include<algorithm> using namespace std; const int maxn=1e6+5; const int INF=0x3f3f3f3f; const int mod=10000007; typedef long long ll; int a[100]; ll dp[65][65][65]; ll Pow(int a,ll n)//快速幂 { ll ans=1,tmp=(ll)a; while(n) { if(n&1) ans=(ans%mod)*(tmp%mod)%mod; tmp=(tmp%mod)*(tmp%mod)%mod; n>>=1; } return ans%mod; } ll dfs(int pos,int now,int all,int limit) //pos是当前数位,now是已经选择的数位的和,all是所需的总和, //limit是限制前一位有没有达到上限。 { if(pos==0) return now==all; if(limit==0 && dp[pos][now][all]!=-1) return dp[pos][now][all]; int upper=limit?a[pos]:1; ll tmp=0; for(int i=0;i<=upper;i++)//数位只有0,1; { tmp+=dfs(pos-1,now+i,all,limit && i==a[pos]); } if(limit==0) dp[pos][now][all]=tmp;//记忆化 return tmp; } ll solve(ll n) { int pos=0; ll ans=1,cnt; while(n) { a[++pos]=n%2; n/=2; } memset(dp,-1,sizeof dp); for(int i=1;i<=pos;i++) { cnt=dfs(pos,0,i,1); ans=(ans%mod*Pow(i,cnt))%mod; } return ans%mod; } int main() { ll n; while(~scanf("%lld",&n)) { printf("%lld\n",solve(n)); } return 0; }
标签:
原文地址:http://www.cnblogs.com/2445512490wh/p/4674931.html