感谢dalao@小粉兔的帮助
dalao’s 博客园,dalao’s 洛谷博客
题目
设 f [ i ] f[i] f[i]表示 i i i转化为二进制后1的个数,求 ∏ i = 1 n f [ i ] \prod_{i=1}^nf[i] i=1∏nf[i]
分析
很容易发现,这应该是一道数位dp的题目,但是怎么做呢,设 d p [ i ] dp[i] dp[i]表示数值小于 n n n的恰好有 k k k个二进制位为1的数的个数,那么这就和 n n n有关系了,如果 n n n的第 j j j位是1,那么说明第 j j j位可以拓展,那么 + + d p [ j ] ++dp[j] ++dp[j],由于每一次算完之后只要在前面加上1就可以得到 d p [ j + 1 ] dp[j+1] dp[j+1],那么 d p [ j + 1 ] + = d p [ j ] dp[j+1]+=dp[j] dp[j+1]+=dp[j],最后dp完之后那么停留的那一位还是可以加上去的,所以最后的代码,感谢小粉兔
代码
#include <cstdio>
#define rr register
using namespace std;
const int mod=10000007;
typedef long long ll;
ll dp[51],n,ans=1,now;
inline ll ksm(ll x,ll y){
rr ll ans=1;
for (;y;y>>=1,x=(x*x)%mod)
if (y&1) ans=(ans*x)%mod;
return ans;
}
signed main(){
scanf("%lld",&n);
for (rr ll j=49;~j;--j){
for (rr ll i=49;i;--i) dp[i]+=dp[i-1];
if (n>>j&1) ++dp[now],++now;
}
++dp[now];
for (rr ll i=1;i<50;++i) ans=ans*ksm(i,dp[i])%mod;
printf("%lld",ans);
return 0;
}
数位DP求解二进制位1的乘积
本文介绍了一种使用数位动态规划(数位DP)的方法来解决一个特定的问题:求解从1到n的所有整数转换为二进制后,1的个数的乘积。通过定义状态dp[i]表示数值小于n的恰好有i个二进制位为1的数的个数,我们展示了如何通过递推公式更新状态,最终求得目标乘积。
9276

被折叠的 条评论
为什么被折叠?



