题意: 给定右端点r , 求
∏ i = 1 i ≤ r s u m ( i ) \prod _{i = 1}^{i\leq r}sum(i) i=1∏i≤rsum(i)
- sum(i)代表,i在二进制表示下有多少个1
- 即 s u m ( i ) = _ _ b u i l t i n _ _ p o p c o u n t ( i ) sum(i)=\_\_builtin\_\_popcount(i) sum(i)=__builtin__popcount(i)
>> face <<
Strategy: 刚拿到这题的时候一点思路也没有 我们这样想: sum(i) == 1 的有多少个, sum(i) == 2的 有多少个 那么答案就是
∏ i = 1 i ≤ c n t i j \prod _{i = 1}^{i \leq cnt} i^{j} i=1∏i≤cntij
- i j → s u m ( n u m ) = = i 的 数 出 现 了 j 次 i^j\to sum(num) == i的数出现了j次 ij→sum(num)==i的数出现了j次
状态: d p [ i ] [ k ] [ j ] → dp[i][k][j]\to dp[i][k][j]→二进制下搜到第i位,能填多少个1, 目前填了j个1状态
目标: ( s u m [ r ] ) ( s u m [ i ] 代 表 1 i 内 的 所 有 合 法 数 的 个 数 ) (sum[r])(sum[i]代表1~i内的所有合法数的个数) (sum[r])(sum[i]代表1 i内的所有合法数的个数)
边界: 本题无
合法判断: 条件转移合法判断
记忆化转移无需预处理
attention: 状态的唯一性
双倍经验: 记忆化细节少
@author: jasonleft 记忆化数位
#include <bits/stdc++.h>
#include <bits/extc++.h>
#define _rep(i, a, b) for (ll i = (a); i <= (b); ++i)
#define _rev(i, a, b) for (ll i = (a); i >= (b); --i)
#define _for(i, a, b) for (ll i = (a); i < (b); ++i)
#define _rof(i, a, b) for (ll i = (a); i > (b); --i)
#define ll long long
#define db double
#define oo 0x3f3f3f3f
#define eps 0.00001
#define all(x) x.begin(), x.end()
#define met(a, b) memset(a, b, sizeof(a))
#define id(x) ((x + 8))
#define bin(x) cerr << #x << " is " << bitset<8>(x) << endl
#define what_is(x) cerr << #x << " is " << x << endl
#define lowbit(x) x &(-x)
using namespace std;
const ll maxn = 55;
const ll mod = 10000007;
ll dp[maxn][maxn][maxn], r, a[maxn], cnt;
inline ll qpow(ll a, ll b)
{
ll ans = 1;
for (; b; b >>= 1, a = a * a % mod)
{
if (b & 1)
ans = a * ans % mod;
}
return ans;
}
ll dfs(ll cur, ll left, ll used, bool up)
{
if (cur == 0)
return used == left;
ll &t = dp[cur][left][used];
if (!up && ~t)
return t;
ll ans = 0;
_rep(i, 0, 1)
{
if (!up || i <= a[cur])
{
ans += dfs(cur - 1, left, used + (i == 1), up && i == a[cur]);
}
}
if (!up)
t = ans;
return ans;
}
ll __ask(ll __)
{
while (__)
a[++cnt] = __ & 1, __ >>= 1;
ll ans = 1;
_rep(i, 2, cnt)
{
ans = (ans * qpow(i, dfs(cnt, i, 0, i))) % mod;
}
return ans;
}
signed main()
{
ios::sync_with_stdio(0);
met(dp, -1);
cin >> r;
cout << __ask(r) << endl;
}