给出
s
u
m
i
sum_{i}
sumi是
i
i
i的二进制中
1
1
1的个数,要求
∏
i
=
1
n
s
u
m
i
\prod_{i=1}^nsum_{i}
∏i=1nsumi,其中
n
≤
1
e
15
n\leq1e15
n≤1e15。
注意到
s
u
m
i
sum_{i}
sumi实际上最多只有
l
o
g
log
log个取值,直接枚举这里面的每一个值,也就是二进制
1
1
1的个数在
1
−
n
1-n
1−n中出现的次数,快速幂计算。
而求
1
−
n
1-n
1−n二进制数中出现
x
x
x次
1
1
1的个数是一个经典的数位dp。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const ll INF=LONG_LONG_MAX;
const int mod=1e7+7;
ll dp[62][62][2];
int a[62];
ll fpow(ll x,ll y) {
ll ans=1;
while(y) {
if(y&1) ans=(ans*x)%mod;
x=(x*x)%mod;
y>>=1;
}
return ans;
}
ll dfs(int pos,int sum,int tot,bool lim) {
if(pos==0) { return sum==tot; }
if(dp[pos][sum][lim]!=-1) return dp[pos][sum][lim];
int up=lim?a[pos]:1;
ll ans=0;
for(int i=0;i<=up;i++) {
ans+=dfs(pos-1,sum+(i==1),tot,lim&&i==a[pos]);
}
return dp[pos][sum][lim]=ans;
}
ll solve(ll x) {
int len=0;
while(x) {
a[++len]=x%2;
x/=2;
}
ll ans=1;
for(int d=1;d<=50;d++) {
memset(dp,-1,sizeof(dp));
ll p=dfs(len,0,d,1);
ans=(ans*fpow(d,p))%mod;
}
return ans;
}
int main() {
ll n;
scanf("%lld",&n);
printf("%lld\n",solve(n));
return 0;
}