定义(sum(i))表示(i)在二进制下(1)的个数
求(prod_{i=1}^{n}sum(i))
暴力非常(sb)显然可以随便写,但是显然也是会(T)
于是我们换个思路
我们设(tot)表示(sum(i)=x)的(i)有多少个,于是答案就是(x^{tot})
我们枚举(x)就行了,(x)显然不会很大,也就是(log_2{n})
之后就可以开始数位(dp)了
我们设(dp[i][0/1][j])表示最高位填到第(i)位,其中最高位填(0/1),一共填了(j)个1一共有多少个数
方程很显然,就是往最高位上填(0/1)
填0的话
[dp[i+1][0][j]+=dp[i][1][j]+dp[i][0][j]
]
填1的话
[dp[i+1][1][j+1]+=dp[i][0][j]+dp[i][1][j]
]
之后我们按照数位(dp)的套路来做就行了
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#define LL long long
#define re register
#define maxn 55
const LL mod=10000007;
const LL P=9988440;
LL n;
int a[maxn];
LL dp[maxn][2][maxn];
inline LL quick(LL a,LL b)
{
LL S=1;
while(b)
{
if(b&1) S=S*a%mod;
b>>=1ll;
a=a*a%mod;
}
return S;
}
inline LL sum(LL x)
{
LL cnt=0;
while(x)
{
if(x&1ll) cnt++;
x>>=1ll;
}
return cnt;
}
inline LL slove(LL x)
{
int num=0;
while(x)
{
++num;
if(x&1ll) a[num]=1;
x>>=1ll;
}//分解数位
dp[1][1][1]=1;
dp[1][0][0]=1;
for(re int i=1;i<num;i++)
for(re int j=0;j<=i;j++)
{
dp[i+1][1][j+1]=(dp[i+1][1][j+1]+dp[i][0][j]+dp[i][1][j]);
dp[i+1][0][j]=(dp[i+1][0][j]+dp[i][0][j]+dp[i][1][j]);
}//dp的过程
LL ans=1;
for(re int T=1;T<=num;T++)//枚举T求出有多少i,sum(i)=T
{
for(re int i=1;i<num;i++)
ans=(ans*quick(T,dp[i][1][T])%mod)%mod;
//先枚举位数比n要小的
int k=T;
if(a[num]) k--;
for(re int i=num-1;i>=1;i--)//之后我们卡前面的[i+1,num]为完全相等,让第i位小于n的第i位,我们就可以让后面的位数随便填了
{
for(re int j=0;j<a[i];j++)
ans=(ans*quick(T,dp[i][j][k])%mod)%mod;
if(a[i]) k--;//别忘了保证前面的数位相等,要减去前面1的个数
if(k<0) break;
}
}
return ans;
//由于一直在卡上界,但最后也没有卡到等于n的情况,于是n的暴力分解数位处理一下就好了
}
int main()
{
scanf("%lld",&n);
std::cout<<sum(n)*slove(n)%mod;
return 0;
}