1 条题解
-
0
P3393 [BJOI2017]同构 题解
题目大意
题目要求对于给定的整数 ,计算一个值,该值为 ,其中 是通过一种贪心分解算法得到的。具体来说,算法使用预处理数组 来分解 ,从而得到 。
解法
预处理数组 的大小为 :
- 表示 个点的某种结构的个数(可能与无标号树相关)。
- 表示 个点的另一种结构的个数。
- 表示使用前 种结构凑出 的方案数。
预处理过程如下:
- 初始化 , 。
- 对于 i N $:
- 计算 (整数除法),如果 为偶数,则加上 。
- 计算 。
- 对于 从 到 ,使用组合数背包计算 。
对于每个测试用例, 读入字符串 。 如果 的长度大于 ,直接输出 (因为对于大 ,答案总是这个常数),否则将 转换为整数 。 如果 去特判。 对于 :
- 初始化 , 。
- 对于 从 到 :
- 。
- 。
- 。
- 计算 。
- 输出
代码
多组数据复杂度 。
具体不想算了#include <bits/stdc++.h> using namespace std; #define LL long long const int mod = 1e9 + 7; const int N = 54; LL f[100], g[100], h[100][100]; inline void solve() { string s; cin >> s; if (s.size() > 20) { cout << "155132763\n"; return; } LL n; sscanf(s.c_str(), "%lld", &n); if (n <= 6) { if (n == 1) { cout << "0\n"; } else if (n <= 5) { cout << "-1\n"; } else { cout << "9\n"; } return; } LL cnt = n, lft = n; for (int i = 1; i <= lft; i++) { LL val = min(lft / i, f[i]); lft -= val * i; cnt -= val; } int n_ = n % mod; LL full = (1LL * n_ * (n_ - 1) / 2) % mod; cout << ((full - cnt) % mod + mod) % mod << '\n'; } inline void build() { f[1] = g[1] = 1; h[1][0] = h[1][1] = 1; for (int i = 2; i <= N; i++) { f[i] = h[(i - 1) >> 1][i - 1]; if (i % 2 == 0) { f[i] += g[i >> 1] * (g[i >> 1] - 1) / 2; } g[i] = h[i - 1][i - 1]; for (int j = 0; j <= N; j++) { LL c = 1; for (int k = 0; i * k <= j && k <= g[i]; k++) { h[i][j] += h[i - 1][j - i * k] * c; c = c * (g[i] - k) / (k + 1); } } } int T; cin >> T; while (T--) { solve(); } } int main() { cin.tie(0)->sync_with_stdio(0); build(); return 0; }更新了题解部分。
信息
- ID
- 8021
- 时间
- 2000ms
- 内存
- 250MiB
- 难度
- 9
- 标签
- 递交数
- 4
- 已通过
- 2
- 上传者