题目链接: P4317 花神的数论题
题目大意
详见题目
solution
设 (f_{i, j, k}) 表示长度为 (i) 最高位为 (j) 的且 (1) 的个数为 (k) 的数的个数
- (j=1, f_{i, j, k} = sumlimits_{p = 0}^{p leqslant 1}sumlimits_{k = 0}^{k leqslant i} f_{i - 1, p, k - 1})
- (j=0, f_{i, j, k} = sumlimits_{p = 0}^{p leqslant 1}sumlimits_{k = 0}^{k leqslant i} f_{i - 1, p, k})
对于(ans_{1, r}) 我们可以采用以下策略 :
设 (len) 为 (r) 的位数, (a_{len}) 为 (r) 的每一位
- 对于首位为 (1) 且前面有 (cnt1) 个 (1) 的 (f) , (res = res * j^{f_{i, 0, j}}, i in [1, len), j in [1, len / 2 - cnt1])
- 对于首位为 (0) 的 (f) , (res = res * j^{f_{i, 1, j}}, i in [1, len), j in [1, i / 2])
那么答案就是 (ans_{1, r})
Code:
/**
* Author: Aliemo
* Data:
* Problem:
* Time: O()
*/
#include <cstdio>
#include <iostream>
#include <string>
#include <cstring>
#include <cmath>
#include <algorithm>
#define int long long
#define rr register
#define inf 1e9
#define MAXN 100010
using namespace std;
const int mod = 10000007;
inline int read() {
int s = 0, f = 0;
char ch = getchar();
while (!isdigit(ch)) f |= ch == '-', ch = getchar();
while (isdigit(ch)) s = s * 10 + (ch ^ 48), ch = getchar();
return f ? -s : s;
}
void print(int x) {
if (x < 0) putchar('-'), x = -x;
if (x > 9) print(x / 10);
putchar(x % 10 + 48);
}
int l, r, len;
int f[80][2][80], a[50];
inline int f_pow(int x, int y) {
int ans = 1;
while (y) {
if (y & 1) ans = ans * x % mod;
x = x * x % mod;
y >>= 1;
}
return ans % mod;
}
inline void init() {
f[1][1][1] = 1, f[1][0][0] = 1;
for (rr int i = 2; i < 64; i++)
for (rr int j = 0; j <= 1; j++)
for (rr int k = 0; k <= i; k++)
for (rr int p = 0; p <= 1; p++)
if (!j) f[i][j][k] += f[i - 1][p][k];
else if (k) f[i][j][k] += f[i - 1][p][k - 1];
}
inline int solve(int x) {
memset(a, 0, sizeof a);
len = 0;
int ans = 0, cnt1 = 1;
while (x) {
a[++len] = x % 2;
ans += a[len];
x /= 2;
}
for (rr int i = len - 1; i >= 1; i--) {
int x = a[i];
if (x) {
for (rr int j = 0; j <= len - cnt1; j++)
if (f[i][0][j] != 0)
ans = (f_pow(j + cnt1, f[i][0][j]) * ans) % mod;
}
cnt1 += x;
}
for (rr int i = 1; i < len; i++)
for (rr int j = 1; j <= i; j++)
if (f[i][1][j] != 0)
ans = (f_pow(j,f[i][1][j]) * ans) % mod;
return ans % mod;
}
signed main() {
init();
r = read();
cout << solve(r);
}