AtCoder Beginner Contest 215(补题)
Posted 佐鼬Jun
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AtCoder Beginner Contest 215(补题)相关的知识,希望对你有一定的参考价值。
C - One More aab aba baa
题目链接: link.
题意:
给一个字符串,让你输出由该字符串的字母组成的所有全排列中的第k个全排列是什么?
思路:
#include <bits/stdc++.h>
using namespace std;
string s;
int k;
int a[8];
int main() {
cin >> s >> k;
sort(s.begin(), s.end());
int len = s.size();
for (int i = 0; i < len; i++) {
a[i] = s[i] - 'a';
}
int cnt = 1;
while (next_permutation(a, a + len)) {
cnt++;
if (cnt == k) break;
}
for (int i = 0; i < len; i++) {
printf("%c", a[i] + 'a');
}
return 0;
}
D - Coprime 2
题目链接: link.
题意:
给你一个长度为n的数组 a 1 a_1 a1… a n a_n an,问你 1 1 1到 m m m中那些数,与 a a a数组所有元素取最大公约数gcd,是1
思路:
把 a a a中元素质因数分解,把里面的质因子取出来,用质因子来筛 1 1 1到 m m m中符合题意的数,也就是与这些质因子不是倍数关系的数。
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
vector<int> a[N];
int n, m;
int st[N];
int main() {
cin >> n >> m;
vector<int> res;
for (int p = 0; p < n; p++) {
int x;
scanf("%d", &x);
for (int i = 2; i <= x / i; i++) {
if (x % i == 0) {
while (x % i == 0) {
x /= i;
}
res.push_back(i);
}
}
if (x > 1) res.push_back(x);
}
vector<int> ans;
sort(res.begin(), res.end());
res.erase(unique(res.begin(), res.end()), res.end());
for (int i = 1; i <= m; i++) {
if (st[i]) continue;
for (int j = 0; j < res.size(); j++) {
int x = res[j];
int y = 1;
while (y * x <= m) {
st[y * x] = 1;
y++;
}
}
}
for (int i = 1; i <= m; i++) {
if (!st[i]) ans.push_back(i);
}
cout << ans.size() << endl;
for (int i = 0; i < ans.size(); i++) {
cout << ans[i] << endl;
}
return 0;
}
E - Chain Contestant
题目链接: link.
题意:
给一个长度为 n n n的字符串,问有多少种子序列满足,在字符串中,相同字母的位置是连续的.
思路:
题目说了,最多10个字母,长度最大1000
所以可以用状压
d
p
dp
dp来想
定义
f
(
i
,
j
,
k
)
f(i,j,k)
f(i,j,k),到了字符串的
i
i
i位置,
j
j
j字母,
k
k
k为10个字母选与没选二进制数字。
f
(
i
,
j
,
k
)
=
f(i,j,k)=
f(i,j,k)=
f
(
i
−
1
,
j
,
k
)
f(i-1,j,k)
f(i−1,j,k),这是不选
i
i
i号位置的字母
f
(
i
,
c
u
r
,
1
<
<
c
u
r
)
+
+
f(i,cur,1 << cur) ++
f(i,cur,1<<cur)++这是第
i
i
i号位置,字母
c
u
r
cur
cur,选的情况
如果选了这个字母,那么这个字母之前出现过的话,必须在前一个位置,必须连续。那么就是
f
(
i
,
c
u
r
,
j
)
+
=
f
(
i
−
1
,
c
u
r
,
j
)
f(i,cur,j )+= f(i - 1,cur,j)
f(i,cur,j)+=f(i−1,cur,j)
含义就是到了
i
i
i号位置了,选cur这个字母,二进制下是
j
j
j,在
i
−
1
i-1
i−1决策时,选了
c
u
r
cur
cur,二进制数仍然是
j
j
j
如果这个字母没出现过,那么就标记这个字母出现了,利用或运算,来对二进制下的数字进行标记
f
(
i
,
c
u
r
,
j
∣
1
<
<
c
u
r
)
+
=
f
(
i
−
1
,
k
,
j
)
f(i,cur,j | 1 << cur) += f(i - 1,k,j)
f(i,cur,j∣1<<cur)+=f(i−1,k,j)
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const ll mod = 998244353;
ll f[1025][10][1025];
int n;
string s;
int main() {
cin >> n >> s;
for (int i = 1; i <= n; i++) {
int cur = s[i - 1] - 'A';
for (int j = 0; j < 1 << 10; j++) {
for (int k = 0; k <= 9; k++) {
f[i][k][j] = f[i - 1][k][j];
}
}
(f[i][cur][1 << cur] += 1) %= mod;
for (int j = 0; j < 1 << 10; j++) {
if (j & (1 << cur)) {
(f[i][cur][j] += f[i - 1][cur][j]) %= mod;
} else {
for (int k = 0; k <= 9; k++) {
(f[i][cur][j | 1 << cur] += f[i - 1][k][j]) %= mod;
}
}
}
}
ll res = 0;
for (int i = 0; i <= 9; i++) {
for (int j = 0; j < 1 << 10; j++) {
(res += f[n][i][j]) %= mod;
}
}
cout << res % mod << endl;
return 0;
}
To be continued
如果你有任何建议或者批评和补充,请留言指出,不胜感激
以上是关于AtCoder Beginner Contest 215(补题)的主要内容,如果未能解决你的问题,请参考以下文章
AtCoder Beginner Contest 115 题解