版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/sugar_free_mint/article/details/86681639
感谢dalao@小粉兔的帮助
dalao’s 博客园,dalao’s 洛谷博客
题目
设 表示 转化为二进制后1的个数,求
分析
很容易发现,这应该是一道数位dp的题目,但是怎么做呢,设 表示数值小于 的恰好有 个二进制位为1的数的个数,那么这就和 有关系了,如果 的第 位是1,那么说明第 位可以拓展,那么 ,由于每一次算完之后只要在前面加上1就可以得到 ,那么 ,最后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;
}