🧩 AtCoder Beginner Contest 262
July 31, 2022About 2 min
🧩 AtCoder Beginner Contest 262
# Info & Summary
- Date:
2022-07-31
- Completion Status: A ✅ / B ✅ / C ✅ / D ✅ / E ❌ / F ❌ / G ❌
- Problem Type:
- D:
DP
- D:
1. D - I Hate Non-integer Number (DP)
https://atcoder.jp/contests/abc262/tasks/abc262_d
1.1 Problem Statement
给定长度为 的 正整数
序列
对于每个数字 , 可以选择, 也可以不选择
一共有 种选择方案(不包括全部不选择)
问: 所有的选择方案中, 有多少种方案可以使得被选择的数字的 算术平方根
为 整数
???
1.2 分析
显而易见, 计数dp
最直观的 dp
定义 : 表示从序列前 个数中选择 个, 且和为 的方案数
但, 数据范围太大, 行不通
改进
修改上述定义为 : 表示从序列前 个数中选择 个, 且 的方案数
但, 无法从 转移到 , 转移方程不好确定, 行不通
最终的 dp 定义
继续修改
dp
的定义 : 表示从序列前 个数中选择 个, 且 的方案数转移方程, 对于 当前数字 :
- 不选择:
- 选择:
1.3 code
#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
int n;
cin >> n;
vector<long long> a(n);
for (int i = 0; i < n; i++)
{
cin >> a[i];
}
long long mod = 998244353;
long long ans = 0;
// 枚举每次选择的数量 [1, n]
for (int i = 1; i <= n; i++)
{
// dp[j][k][l]: 从前j个数中选择k个, mod i的余数等于 l, 的方案
vector<vector<vector<long long>>> dp(n + 1, vector<vector<long long>>(i + 1, vector<long long>(i, 0)));
dp[0][0][0] = 1;
for (int j = 0; j < n; j++)
{
for (int k = 0; k <= i; k++)
{
for (int l = 0; l < i; l++)
{
dp[j + 1][k][l] += dp[j][k][l];
dp[j + 1][k][l] %= mod;
if (k != i)
{
dp[j + 1][k + 1][(l + a[j]) % i] += dp[j][k][l];
dp[j + 1][k + 1][(l + a[j]) % i] %= mod;
}
}
}
}
// cout << dp[n][i][0] << endl;
ans = (ans + dp[n][i][0] % mod) % mod;
}
cout << ans << endl;
return 0;
}