LuoguP1586 题解

也可以在 LuoguP1586 (tencentcs.com) 获得更好的阅读体验。

Luogu_P1586 题解

一道比较简单的题目,看到求种类数,考虑 DP。

\(f_{i,j}\) 表示第 \(i\) 个数划分为 \(j\) 个数的平方的种类数,那么很显然的,当你从 \(i\) 中划出一个平方数 \(k^2\),那么问题相当于变成了 如何将 \(i-k^2\) 划分为 \(j-1\) 个数,于是状态转移方程就呼之欲出了:\(f_{i,j}=\sum\limits_{k=1}^{k^2\le i}f_{i-k^2,j-1}\)

这个玩意的转移只能按照 \(k,i,j\) 的顺序枚举,不然会重复统计/漏统计一些数。边界条件很显然的是 \(f_{0,0}=1\),因为此时我们的目标已经达成了。

多测注意清空。

#include <bits/stdc++.h>
using namespace std;

#define endl '\n'
#define int long long
#define lson (p << 1)
#define rson ((p << 1) | 1)
#define mid ((l + r) >> 1)

const int MAXN = 50005;
int n, f[MAXN][5], T, ret;

signed main(void) {
    ios::sync_with_stdio(false);
    cin.tie(0);
    f[0][0] = 1;
    for (int i = 1; i * i <= 32768; ++i) {
        for (int j = i * i; j <= 32768; ++j) {
            for (int k = 1; k <= 4; ++k) f[j][k] += f[j - i * i][k - 1];
        }
    }
    cin >> T;
    while (T--) {
        cin >> n;
        for (int i = 1; i <= 4; ++i) ret += f[n][i];
        cout << ret << endl; ret = 0;
    }
    return 0;
}
posted @ 2022-11-09 21:33  小蛐蛐awa  阅读(29)  评论(0)    收藏  举报