又是恶心的数位dp···
调了好久因为一个地方不该%给%了QAQ
看题还是有思路的···但还是参考了题解···数位dp要加强吧qwq
f[i][j][0/1]表示二进制下i位数最高位是0/1,有j个1的个数
然后快速幂就好了
很常规的套路但就是写不了···
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define maxn 200
#define LL long long
using namespace std;
LL n,f[maxn][maxn][2],ans=1,sum[maxn];
const int mod=10000007;
int len,a[maxn],cnt;
LL qpow(LL x,LL k){
LL ret=1;
while(k){
if(k&1LL) (ret*=x)%=mod;
(x*=x)%=mod;
k>>=1LL;
}
return ret;
}
int main(){
scanf("%lld",&n); LL tmp=n;
while(tmp){
a[++len]=(tmp&1);
tmp>>=1;
}
f[1][0][0]=f[1][1][1]=1;
for(int i=2;i<=len;i++)
for(int j=0;j<=i;j++){
f[i][j][0]=(f[i-1][j][0]+f[i-1][j][1]);//这里不能%mod!
if(j!=0) f[i][j][1]=(f[i-1][j-1][0]+f[i-1][j-1][1]);
}
for(int i=len;i;i--)//已经确定了前i位
if(a[i]){//这一位是1
for(int j=1;j<=i;j++)//
(ans*=qpow(j+cnt,f[i][j][0]))%=mod;
if(cnt>0) (ans*=cnt)%=mod;//后面都填0
cnt++;
}
(ans*=cnt)%=mod;//别忘了n本身
printf("%lld\n",ans);
return 0;
}