题目链接
https://www.luogu.com.cn/problem/P1356
思路
n n n的大小只有 1 0 4 10^4 104, k k k的大小只有 100 100 100,我们令 d p [ i ] [ j ] dp[i][j] dp[i][j]表示前 i i i个数字构成的所有表达式,表达式的值模 k k k为 j j j是否存在。
则转移方程为:
d p [ i ] [ m o d ( j + a [ i ] ) ] ∣ = d p [ i − 1 ] [ j ] dp[i][mod(j + a[i])] |= dp[i - 1][j] dp[i][mod(j+a[i])]∣=dp[i−1][j]和 d p [ i ] [ m o d ( j − a [ i ] ) ] ∣ = d p [ i − 1 ] [ j ] dp[i][mod(j - a[i])] |= dp[i - 1][j] dp[i][mod(j−a[i])]∣=dp[i−1][j]
时间复杂度: O ( m n k ) O(mnk) O(mnk)
代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define double long double
typedef long long i64;
typedef unsigned long long u64;
typedef pair<int, int> pii;
const int N = 1e4 + 5, M = 1e2 + 5;
const int mod = 10007;
const int inf = 0x3f3f3f3f3f3f3f3f;
std::mt19937 rnd(time(0));
int n, k;
int a[N];
int MOD(int x)
{
return (x % k + k) % k;
}
void solve(int test_case)
{
cin >> n >> k;
for (int i = 1; i <= n; i++)
{
cin >> a[i];
}
vector<vector<int>>dp(n + 1, vector<int>(k, 0));
dp[1][MOD(a[1])] = 1;
for (int i = 2; i <= n; i++)
{
for (int j = 0; j < k; j++)
{
int res = MOD(j + a[i]);
dp[i][res] |= dp[i - 1][j];
res = MOD(j - a[i]);
dp[i][res] |= dp[i - 1][j];
}
}
if (dp[n][0])
{
cout << "Divisible" << endl;
}
else cout << "Not divisible" << endl;
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int test = 1;
cin >> test;
for (int i = 1; i <= test; i++)
{
solve(i);
}
return 0;
}