【LG4317】花神的數論題
阿新 • • 發佈:2019-01-05
【LG4317】花神的數論題
題面
題解
設\(f_{i,up,tmp,d}\)表示當前在第\(i\)位,是否卡上界,有\(tmp\)個一,目標是幾個一的方案數
最後將所有\(d\)固定,套數位\(dp\)的板子
然後快速冪乘起來就好了
程式碼
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <algorithm> #include <vector> using namespace std; #define int long long const int Mod = 1e7 + 7; int N, f[55][2][55][55]; vector<int> digit; int fpow(int x, int y) { int res = 1; while (y) { if (y & 1) res = 1ll * res * x % Mod; x = 1ll * x * x % Mod; y >>= 1ll; } return res; } int dfs(int o, bool up, int tmp, int d) { if (o == -1) return tmp == d; if (~f[o][up][tmp][d]) return f[o][up][tmp][d]; int lim = up ? digit[o] : 1, res = 0; for (int i = 0; i <= lim; i++) res = res + dfs(o - 1, up && i == lim, tmp + (i == 1), d); return f[o][up][tmp][d] = res; } int ans[100]; int solve(int n) { while (n) digit.push_back(n & 1ll), n >>= 1ll; digit.push_back(0); for (int i = 1; i <= 50; i++) { memset(f, -1, sizeof(f)); ans[i] = dfs(digit.size() - 1, 1, 0, i); } int res = 1; for (int i = 1; i <= 50; i++) res = 1ll * res * fpow(i, ans[i]) % Mod; return res; } signed main () { cin >> N; printf("%lld\n", solve(N)); return 0; }