2020牛客暑期多校训练营(第六场)
k-bag
题意 :你有一个字符串 a, 字符串a可以分为 x份, 每份长度为 k且只含有 1到k的数字 (随便怎么排)
然后给你字符串b问你,b是字符串a的子串吗?是就是 yes, 不是就是 no。
题解:
要使字符串 b 是a的子串
那么 b的第一份与最后一份 可以随便排, 中间必须每长度k分成一份且每份只含有1到k的数字。
如果第一份的位置确定, 那么 后面的位置也随之确定。
所以枚举 第一份的所有可能的位置, 判断是否有答案。
我们可以用一个 (le[i])表示 第i位数 右边第一个不合法的位置。
代码:
#include<bits/stdc++.h>
using namespace std;
const int N = 2e6 + 7;
unordered_map<int, int>vis;
int le[N], a[N];
int main() {
int t; scanf("%d", &t);
while (t--) {
vis.clear();
int n, k; scanf("%d %d", &n, &k);
int f = 0;
for (int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
if (a[i] > k) {
f = 1;
}
}
if (f) {
puts("NO");
} else if (k >= n) {
int l = 1;
while (l <= n && vis[a[l]] == 0) vis[a[l]] = 1, l++;
vis.clear();
int r = n;
while(r <= n && vis[a[r]] == 0) vis[a[r]] = 1, r--;
if (l > r) {
puts("YES");
} else {
puts("NO");
}
} else {
int l = 1;
for (int i = 1; i <= n; i++) {
while (l <= n && vis[a[l]] == 0) {
vis[a[l]] = 1;
l++;
}
le[i] = l;
vis[a[i]] = 0;
}
int flag = 0;
for (int i = 1; i < le[1]; i++) {
int ok = 0;
for (int j = i + 1; j <= n; j += k) {
if (le[j] > n) {
break;
}
if (le[j] - j != k) {
ok = 1;
break;
}
}
if (ok == 0) {
flag = 1;
break;
}
}
if (flag) {
puts("YES");
} else {
puts("NO");
}
}
}
}
题意:给你一个数字A, 问再 1 到 A中, 有多少对 (x, y)满足 x的数字之和 大于 y的数字之和 且 x (le) y
题解:
dfs 暴力枚举两个数
判断是否合法。
然后加 记忆化。
再dfs里面 相同参数进去出来结果肯定一样,所以加上记忆化会大大减少时间。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 100 + 7;
ll dp[N][2000][2][2][2];
int up[N], n;
const ll mod = 1e9 + 7;
ll dfs(int p, int sum, int f, int f1,int ok) {
if (p == n) {
if (ok && sum > 1000) {
return 1;
}
return 0;
}
if (dp[p][sum][f][f1][ok] != -1) return dp[p][sum][f][f1][ok];
int maxn, maxn1;
if (f) {
maxn = up[p];
} else {
maxn = 9;
}
if (f1) {
maxn1 = up[p];
} else {
maxn1 = 9;
}
ll ans = 0;
for (int i = 0; i <= maxn; i++) {
for (int j = 0; j <= maxn1; j++) {
if (!ok && i > j) continue;
ans = (ans + dfs(p + 1, sum + i - j, f && i == maxn, f1 && j == maxn1, ok | (j > i? 1: 0)));
ans = ans % mod;
}
}
return dp[p][sum][f][f1][ok] = ans;
}
int main() {
string s;
cin >> s;
for (int i = 0; i < s.length(); i++) {
up[i] = s[i] - '0';
}
n = s.length();
memset(dp, -1, sizeof(dp));
ll ans = dfs(0, 1000, 1, 1, 0);
printf("%lld
", ans);
}