题面
题解
数位dp都是套路题
设$f[i][0/1][k][l]$表示$dp$到第$i$位,是否卡上界,现在$1$的个数为$k$,所求的$1$的个数为$l$的方案数
转移看一下代码吧,很好懂的。
$ecause10^7+7$不是质数,$ herefore;f$要开$ ext{long long}$
代码
#include<cstdio>
#include<cstring>
#include<cctype>
#include<algorithm>
#include<vector>
#define RG register
#define file(x) freopen(#x".in", "r", stdin);freopen(#x".out", "w", stdout);
#define clear(x, y) memset(x, y, sizeof(x))
#define int long long
inline int read()
{
int data = 0, w = 1; char ch = getchar();
while(ch != '-' && (!isdigit(ch))) ch = getchar();
if(ch == '-') w = -1, ch = getchar();
while(isdigit(ch)) data = data * 10 + (ch ^ 48), ch = getchar();
return data * w;
}
const int Mod(10000007);
int n;
long long f[60][2][60][60];
std::vector<int> dig;
inline int fastpow(int x, int y)
{
int ans = 1;
while(y)
{
if(y & 1) ans = 1ll * ans * x % Mod;
x = 1ll * x * x % Mod, y >>= 1;
}
return ans;
}
int dfs(int x, int lim, int cnt, int max)
{
if(x == -1) return cnt == max;
if(~f[x][lim][cnt][max]) return f[x][lim][cnt][max];
int newlim = lim ? dig[x] : 1, ans = 0;
for(RG int i = 0; i <= newlim; i++)
ans += dfs(x - 1, lim && newlim == i, cnt + (i == 1), max);
return f[x][lim][cnt][max] = ans;
}
int ans[60];
int solve(int n)
{
while(n) dig.push_back(n & 1), n >>= 1;
dig.push_back(0);
for(RG int i = 1; i <= 50; i++)
{
clear(f, -1);
ans[i] = dfs(dig.size() - 1, 1, 0, i);
}
int tot = 1;
for(RG int i = 1; i <= 50; i++) tot = 1ll * tot * fastpow(i, ans[i]) % Mod;
return tot;
}
signed main()
{
n = read();
printf("%lld
", solve(n));
return 0;
}