题目描述
题目大意:sum(i)表示i的二进制中1的个数,求 ∏i=1nsum(i)
题解
问题转化为有多少个数二进制中1的个数为i
f(i,0/1,j)表示二进制为i位数,是否卡上界,有j个1的数的个数
dp完了之后快速幂一下就行了
代码
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
#define LL long long
#define Mod 10000007
LL num,ans;
int n,dig[100];
LL f[100][2][100],cnt[100];
int calc(LL x)
{
int ans=0;
while (x) dig[++ans]=x&1,x>>=1;
for (int i=1;i<=ans>>1;++i)
swap(dig[i],dig[ans-i+1]);
return ans;
}
LL fast_pow(LL a,LL p)
{
LL ans=1LL;
for (;p;p>>=1LL,a=a*a%Mod)
if (p&1LL)
ans=ans*a%Mod;
return ans;
}
int main()
{
scanf("%lld",&num);
n=calc(num);
f[1][0][0]=f[1][1][1]=1LL;
for (int i=1;i<n;++i)
for (int j=0;j<=1;++j)
for (int k=0;k<=i;++k)
{
int lim=j?dig[i+1]:1;
LL now=f[i][j][k];
for (int p=0;p<=lim;++p)
f[i+1][(j&&p==dig[i+1])?1:0][p?k+1:k]+=now;
}
for (int j=0;j<=1;++j)
for (int k=1;k<=n;++k)
cnt[k]+=f[n][j][k];
ans=1LL;
for (int i=1;i<=n;++i)
ans=ans*fast_pow(i,cnt[i])%Mod;
printf("%lld\n",ans);
}