bzoj3209 花神的数论题 数位DP
2017-07-25 16:12
344 查看
一开始想的是先预处理出n位的答案,因为假设当前给出的数x有y位,那么y-1位的答案是固定的,我只要处理y位的答案就可以了,问题是这样太复杂。。。
设f[i][j]表示i位有j个1的答案,那么明显有f[i][j]=f[i-1][j]+f[i-1][j-1],表示第i位选0或1.
然后最后统计一下答案,就是每一种出现了多少次。。
其实挺简单的,基本想出来了,但是数位dp不熟,想的复杂了。
设f[i][j]表示i位有j个1的答案,那么明显有f[i][j]=f[i-1][j]+f[i-1][j-1],表示第i位选0或1.
然后最后统计一下答案,就是每一种出现了多少次。。
其实挺简单的,基本想出来了,但是数位dp不熟,想的复杂了。
#include<cstdio> #include<cstring> #include<algorithm> #define fo(i,a,b) for(int i=a;i<=b;i++) #define fd(i,a,b) for(int i=a;i>=b;i--) using namespace std; const int N=1e5+5; const int mo=10000007; typedef long long ll; ll n; ll sum[100],f[100][100],g[100]; int wei ; int tot; ll ans; inline void pre() { f[0][0]=1; fo(i,1,60) { f[i][0]=1; fo(j,1,i) f[i][j]=f[i-1][j-1]+f[i-1][j]; } } ll solve(int x) { ll sum=0; fd(i,tot,1) { if (wei[i]==1) { sum+=f[i-1][x]; --x; } if (x<0)break; } return sum; } ll pow(ll a,ll b) { ll ret=1; while (b) { if (b&1)ret=ret*a%mo; a=a*a%mo; b>>=1; } return ret; } int main() { pre(); scanf("%lld",&n); ++n; tot=0; while (n) { wei[++tot]=n&1; n>>=1; } ans=1ll; fo(i,1,tot) ans=ans*pow(i,solve(i))%mo; printf("%lld\n",ans%mo); return 0; }
相关文章推荐
- bzoj 3209: 花神的数论题 数位dp
- [BZOJ3209]花神的数论题(数位dp)
- [数位DP] BZOJ 3209 花神的数论题
- bzoj 3209 花神的数论题(数位dp)
- bzoj 3209: 花神的数论题 数位dp
- BZOJ3209:花神的数论题(数位dp)
- [数位dp] bzoj 3209 花神的数论题
- bzoj3209: 花神的数论题(数位Dp)
- [数位dp] bzoj 3209 花神的数论题
- 【BZOJ3209】花神的数论题 数位DP
- BZOJ 3209: 花神的数论题 (数位dp)
- BZOJ_3209_花神的数论题_组合数+数位DP
- [Bzoj3209]花神的数论题(数位dp)
- 【bzoj3209】花神的数论题 数位DP
- BZOJ3209 花神的数论题(数位dp)
- [BZOJ3209]花神的数论题(数位dp)
- BZOJ 3209: 花神的数论题【数位dp】
- bzoj 3209: 花神的数论题 (数位DP)
- 【BZOJ3209】花神的数论题 数位DP(我姿势不标准,但是可能更好写)
- BZOJ 3209: 花神的数论题 [数位DP]