BZOJ 3209 花神的数论题 数位dp
2017-10-16 14:54
381 查看
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
一开始看成了sigma(sum(1)……sum(n)),结果就随手上了= =
原来是乘积……突然不会
好吧其实还行,只要把问题转化掉就好了,
10^15约莫2^50,所以最多50个1,
枚举1的个数x,问题变成求出1~n内每个数的二进制含1个数恰好为x的个数,
假设这个个数为y,那么对答案的贡献就是x^y
怎么求呢……数位dp吧= =直接二进制的数位dp
一开始没加快速幂而10^8 TLE了好久……
我还以为是记忆化错了呢= =气死
#include<bits/stdc++.h> #define ll long long using namespace std; const ll Mod=10000007; ll n,f[55][55]; int len,a[55]; ll dfs(int now,bool limit,int num){ if (num<0) return 0; if (now>len) return num==0; if (!limit && f[now][num]>=0) return f[now][num]; ll t=dfs(now+1,limit&(a[now]==0),num); if (!limit || a[now]==1) t+=dfs(now+1,limit,num-1); if (!limit) f[now][num]=t; return t; } ll ksm(ll a,ll b){ ll ans=1LL;a%=Mod; while (b){ if (b&1LL) ans=ans*a%Mod; b>>=1LL; a=a*a%Mod; } return ans; } int main(){ scanf("%lld",&n); len=0; while (n) a[++len]=n&1LL,n>>=1LL; for (int i=1;i<=(len>>1);i++) swap(a[i],a[len-i+1]); memset(f,255,sizeof(f)); ll ans=1LL; for (int i=1;i<=len;i++){ ll t=ksm(i,dfs(1,1,i)); ans=ans*t%Mod; } printf("%lld\n",ans); return 0; }
相关文章推荐
- BZOJ3209 花神的数论题(数位dp)
- bzoj 3209: 花神的数论题 数位dp
- BZOJ_3209_花神的数论题_组合数+数位DP
- [Bzoj3209]花神的数论题(数位dp)
- 【BZOJ3209】花神的数论题 数位DP(我姿势不标准,但是可能更好写)
- 【bzoj3209】花神的数论题 数位DP
- [数位dp] bzoj 3209 花神的数论题
- [数位dp] bzoj 3209 花神的数论题
- bzoj 3209: 花神的数论题【数位dp】
- 【BZOJ3209】花神的数论题 数位DP
- BZOJ 3209: 花神的数论题 (数位dp)
- BZOJ 3209: 花神的数论题【数位dp】
- bzoj 3209: 花神的数论题 数位dp
- [数位DP] BZOJ 3209 花神的数论题
- [bzoj3209]花神的数论题_数位dp
- [BZOJ3209]花神的数论题(数位dp)
- bzoj 3209 花神的数论题(数位dp)
- [BZOJ]3209: 花神的数论题 数位DP
- bzoj3209 花神的数论题 数位DP
- bzoj 3209: 花神的数论题 (数位DP)