把回文拆分的归纳定义翻译成计数递推:奇数项抄前一项,偶数项再加上半值项,O(N) 递推取模。
OJ: roj
题目 ID: 10029
难度:普及
标签:递推计数整数划分python
创建: 2026-10-02 19:05
更新: 2026-10-04 22:16
题目描述
数的回文拆分从归纳角度定义:单个正整数
| 样例输入 | 样例输出 |
|---|---|
4 |
4 |
20 |
60 |
思路
按定义,值 A+A 型(A+x+A 型(贡献
参考代码
Python 版:
python
#!/usr/bin/env python3
# Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
# rbook: -> https://rbook.roj.ac.cn https://rbook2.roj.ac.cn
# rainboy的学习导航网站: https://idx.roj.ac.cn
# create_at: 2026-10-02 19:07
# update_at: 2026-10-02 19:07
import sys
MOD = 1_000_000_007
def solve() -> None:
"""读入 N,输出 N 的回文拆分数 mod 1e9+7。"""
n = int(sys.stdin.buffer.read())
# f[k] = k 的回文拆分数。由归纳定义推出:f(1)=1,
# 奇数与前一个偶数相等 f(2m+1)=f(2m),偶数再叠上"两半相同"的 f(m)。
f = [0, 1] + [0] * (n - 1)
for k in range(2, n + 1):
f[k] = (f[k - 1] + (f[k // 2] if k % 2 == 0 else 0)) % MOD
print(f[n])
if __name__ == "__main__":
solve()C++ 版(同一算法):
cpp
/**
* Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
* rbook: -> https://rbook.roj.ac.cn https://rbook2.roj.ac.cn
* rainboy的学习导航网站: https://idx.roj.ac.cn
* create_at: 2026-10-04 22:16
* update_at: 2026-10-04 22:16
*/
#include <cstdio>
typedef long long ll;
const ll MOD = 1e9 + 7;
const int MAXN = 1005;
ll f[MAXN]; // f[i] 表示值 i 的回文拆分数(mod 1e9+7)
int main() {
ll n;
scanf("%lld", &n);
// 由归纳定义推出:
// 基础型恒有 1 个,A+A 型贡献 f(n/2)(n 为偶数),
// A+x+A 型贡献 sum_{a<=floor((n-1)/2)} f(a),用前缀和化简后得
// 关键恒等式 f(2m)=f(2m+1)=F(m),等价于下面两条递推:
// 奇数项抄前一项,偶数项 = 前一项 + 半值项。
f[1] = 1;
for (ll k = 2; k <= n; ++k) {
if (k % 2 == 1)
f[k] = f[k - 1];
else
f[k] = (f[k - 1] + f[k / 2]) % MOD;
}
printf("%lld\n", f[n]);
return 0;
}