BZOJ 3209 花神的数论题 数位DP
2015-01-30 19:29
169 查看
题目大意:求1~N中所有数的二进制的1出现的个数的乘积。
思路:简单的数位DP。首先预处理出一个数组:f[i][j]表示i位二进制数中有j个1的数字有多少个。转移显然是f[i][j] = f[i - 1][j - 1] + f[i - 1][j]。
之后按照二进制位从高到低统计答案。对于要统计的这个数的第i为是1的话,我们就可以知道前面000……0000~111……1111这些数的答案,把这些加到ans数组中,注意要加上之前的所有的1的数量。
之后就是一个快速幂出解了。
CODE:
思路:简单的数位DP。首先预处理出一个数组:f[i][j]表示i位二进制数中有j个1的数字有多少个。转移显然是f[i][j] = f[i - 1][j - 1] + f[i - 1][j]。
之后按照二进制位从高到低统计答案。对于要统计的这个数的第i为是1的话,我们就可以知道前面000……0000~111……1111这些数的答案,把这些加到ans数组中,注意要加上之前的所有的1的数量。
之后就是一个快速幂出解了。
CODE:
#define _CRT_SECURE_NO_WARNINGS #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define MAX 110 #define MO 10000007 using namespace std; long long f[MAX][MAX],ans[MAX]; inline void Solve(long long x) { int len = 0; while(x >> len) ++len; int now = 0; for(int i = len; ~i; --i) { if((x >> (i - 1))&1) { ++now; for(int j = 0; j <= i - 1; ++j) ans[j + now - 1] += f[i - 1][j]; } } } long long QuickPower(long long x,long long y) { long long re = 1; while(y) { if(y&1) re = re * x % MO; y >>= 1; x = x * x % MO; } return re; } int main() { for(int i = 0; i <= 60; ++i) { f[i][0] = 1; for(int j = 1; j <= i; ++j) f[i][j] = f[i - 1][j] + f[i - 1][j - 1]; } long long x; cin >> x; Solve(x + 1); long long output = 1; for(int i = 1; i <= 60; ++i) for(int j = 1; j <= ans[i]; ++j) output = output * i % MO; cout << output % MO << endl; return 0; }
相关文章推荐
- BZOJ 3209: 花神的数论题 数位DP
- bzoj 3209: 花神的数论题
- [数位DP] BZOJ 3209 花神的数论题
- bzoj 3209: 花神的数论题(数位DP+快速幂)
- 【bzoj3209】花神的数论题 数位DP
- BZOJ 3209 花神的数论题
- bzoj 3209: 花神的数论题 (数位DP)
- 【BZOJ3209】花神的数论题 数位DP(我姿势不标准,但是可能更好写)
- [BZOJ3209]花神的数论题
- [bzoj3209]花神的数论题
- 【bzoj 3209】花神的数论题(组合数学)
- BZOJ3209: 花神的数论题
- [bzoj3209][花神的数论题] (数位dp+费马小定理)
- bzoj3209 花神的数论题
- BZOJ_3209_花神的数论题_组合数+数位DP
- bzoj3209: 花神的数论题(数位Dp)
- BZOJ 3209 花神的数论题 数位dp
- BZOJ3209 花神的数论题(数位dp)
- bzoj 3209: 花神的数论题 && 喵哈哈村的秘境探险(四)
- BZOJ 3209 花神的数论题