D
题意:
找相邻对...
思路:
找到相邻对
...a,b...a,b...
...a,b...b,a...
其实只要去查询位置就好了,排序处理掉左右的情况,
set避免计算到同一对,注意minmax
代码:
/*
链,找相邻不相等的对数
排序消除左右位置,st去重
要消除重复,我可以将这一对记录下来
*/
#include <bits/stdc++.h>
using namespace std;
void solve()
{
int n; cin >> n;
vector<int> a(2*n);
for(int i = 0; i < n+n; i++) cin >> a[i];
vector<vector<int>> pos(n+1);
for(int i = 0; i < n + n; i++) pos[a[i]].push_back(i);
set<pair<int,int>> st;
for(int i = 0; i + 1< n + n; i++)
{
int x = a[i], y = a[i+1];
if(pos[x][0] + 1 == pos[x][1]) continue;
if(pos[y][0] + 1 == pos[y][1]) continue;
vector<int> v{pos[x][0], pos[x][1], pos[y][0], pos[y][1]};
sort(v.begin(), v.end());
if(v[0]+1 == v[1] && v[2] + 1 == v[3]) st.emplace(minmax(x,y));
}
cout << st.size() << '\n';
}
int main()
{
int t; cin >> t;
while(t--)
{
solve();
}
return 0;
}
E
题意:
S经过操作变成T,每次操作S相同字符全部变换,问最少操作次数
思路:
1.能不能变?
1.相等的字符总是相等的,s[i] = s[j] and t[i] != t[j] -> 无解
2.操作之后,肯定存在s[i] = s[j] and t[i] != t[j] 的情况(循环变化)-> 没有外部点 -> |字符集T的大小| == 26
eg:S : abc...z T:bc...za
2.最小次数?
对于循环变化 -> 引入外部字符
abcd -> bcda
ans = 除自环的边数 + 环的个数(破坏成链处理需要+1)
/*
1.非法:没有外部点,s[i] = s[j] && t[i] != t[j]
2.最少次数
ans = 除去自环的边数 + 环的个数
最后能结合成一张图 -> 并查集,连通性
边数:并查集
环:结点个数(并查集大小存储的连通块结点个数) == 边数
自环:e[i] == 1 and dsu.find(i) == 1
*/
#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 10;
struct DSU{
int fa[N], sz[N];
void init(int n){
for(int i = 0; i <= n; i++) fa[i] = i, sz[i] = 1;
}
int find(int x){
return fa[x] == x ? x : fa[x] = find(fa[x]);
}
void merge(int x, int y)
{
int rx = find(x), ry = find(y);
if(rx == ry)return;
if(sz[rx] < sz[ry]) swap(rx,ry);
sz[rx] += sz[ry];
fa[ry] = rx;
}
int getsz(int x)
{
return sz[find(x)];
}
}dsu;
int main()
{
int n; cin >> n;
string S, T; cin >> S >> T;
if(S == T)
{
cout << 0 << '\n';
return 0;
}
vector<int> f(26, -1);
for(int i = 0; i < n; i++)
{
int x = S[i] - 'a', y = T[i] - 'a';
if(f[x] == -1){
f[x] = y;
}else if(y != f[x]){
cout << -1 << '\n';
return 0;
}
}
dsu.init(26);
vector<bool> vis(26,0);
int ans = 0;
for (int i = 0; i < 26; i++) {
if (f[i] != -1) {
vis[f[i]] = true;
}
if (f[i] != -1 && f[i] != i) {
ans++;
dsu.merge(i, f[i]);
}
}
if(count(vis.begin(), vis.end(), true) == 26)
{
cout << -1 << '\n';
return 0;
}
vector<int> e(26);
for (int i = 0; i < 26; i++) {
if (vis[i]) {
e[dsu.find(i)]++;
}
}
for (int i = 0; i < 26; i++) {
if (dsu.find(i) == i && e[i] > 1 && e[i] == dsu.getsz(i)) {
ans++;
}
}
cout << ans << '\n';
return 0;
}
F
题意:
序列所有子段和的k次幂的和
思路:
【组合数】
1.子段:所有子段一次性求解很难,于是定义每个子段开头/结尾
2.k次幂:0,1,2... k 次幂多项式的和
3.增量:二项式定理
定义:f[i][k]:以r为结尾的k次幂的和
转移:推式子,展开二项式就是转移方程


来源:B站清北信息学奥赛abc399讲解视频
代码:
//from jiangly
#include <bits/stdc++.h>
using i64 = long long;
using u64 = unsigned long long;
using u32 = unsigned;
using u128 = unsigned __int128;
template<class T>
constexpr T power(T a, u64 b, T res = 1) {
for (; b != 0; b /= 2, a *= a) {
if (b & 1) {
res *= a;
}
}
return res;
}
template<u32 P>
constexpr u32 mulMod(u32 a, u32 b) {
return u64(a) * b % P;
}
template<u64 P>
constexpr u64 mulMod(u64 a, u64 b) {
u64 res = a * b - u64(1.L * a * b / P - 0.5L) * P;
res %= P;
return res;
}
constexpr i64 safeMod(i64 x, i64 m) {
x %= m;
if (x < 0) {
x += m;
}
return x;
}
constexpr std::pair<i64, i64> invGcd(i64 a, i64 b) {
a = safeMod(a, b);
if (a == 0) {
return {b, 0};
}
i64 s = b, t = a;
i64 m0 = 0, m1 = 1;
while (t) {
i64 u = s / t;
s -= t * u;
m0 -= m1 * u;
std::swap(s, t);
std::swap(m0, m1);
}
if (m0 < 0) {
m0 += b / s;
}
return {s, m0};
}
template<std::unsigned_integral U, U P>
struct ModIntBase {
public:
constexpr ModIntBase() : x(0) {}
template<std::unsigned_integral T>
constexpr ModIntBase(T x_) : x(x_ % mod()) {}
template<std::signed_integral T>
constexpr ModIntBase(T x_) {
using S = std::make_signed_t<U>;
S v = x_ % S(mod());
if (v < 0) {
v += mod();
}
x = v;
}
constexpr static U mod() {
return P;
}
constexpr U val() const {
return x;
}
constexpr ModIntBase operator-() const {
ModIntBase res;
res.x = (x == 0 ? 0 : mod() - x);
return res;
}
constexpr ModIntBase inv() const {
return power(*this, mod() - 2);
}
constexpr ModIntBase &operator*=(const ModIntBase &rhs) & {
x = mulMod<mod()>(x, rhs.val());
return *this;
}
constexpr ModIntBase &operator+=(const ModIntBase &rhs) & {
x += rhs.val();
if (x >= mod()) {
x -= mod();
}
return *this;
}
constexpr ModIntBase &operator-=(const ModIntBase &rhs) & {
x -= rhs.val();
if (x >= mod()) {
x += mod();
}
return *this;
}
constexpr ModIntBase &operator/=(const ModIntBase &rhs) & {
return *this *= rhs.inv();
}
friend constexpr ModIntBase operator*(ModIntBase lhs, const ModIntBase &rhs) {
lhs *= rhs;
return lhs;
}
friend constexpr ModIntBase operator+(ModIntBase lhs, const ModIntBase &rhs) {
lhs += rhs;
return lhs;
}
friend constexpr ModIntBase operator-(ModIntBase lhs, const ModIntBase &rhs) {
lhs -= rhs;
return lhs;
}
friend constexpr ModIntBase operator/(ModIntBase lhs, const ModIntBase &rhs) {
lhs /= rhs;
return lhs;
}
friend constexpr std::istream &operator>>(std::istream &is, ModIntBase &a) {
i64 i;
is >> i;
a = i;
return is;
}
friend constexpr std::ostream &operator<<(std::ostream &os, const ModIntBase &a) {
return os << a.val();
}
friend constexpr bool operator==(const ModIntBase &lhs, const ModIntBase &rhs) {
return lhs.val() == rhs.val();
}
friend constexpr std::strong_ordering operator<=>(const ModIntBase &lhs, const ModIntBase &rhs) {
return lhs.val() <=> rhs.val();
}
private:
U x;
};
template<u32 P>
using ModInt = ModIntBase<u32, P>;
template<u64 P>
using ModInt64 = ModIntBase<u64, P>;
struct Barrett {
public:
Barrett(u32 m_) : m(m_), im((u64)(-1) / m_ + 1) {}
constexpr u32 mod() const {
return m;
}
constexpr u32 mul(u32 a, u32 b) const {
u64 z = a;
z *= b;
u64 x = u64((u128(z) * im) >> 64);
u32 v = u32(z - x * m);
if (m <= v) {
v += m;
}
return v;
}
private:
u32 m;
u64 im;
};
template<u32 Id>
struct DynModInt {
public:
constexpr DynModInt() : x(0) {}
template<std::unsigned_integral T>
constexpr DynModInt(T x_) : x(x_ % mod()) {}
template<std::signed_integral T>
constexpr DynModInt(T x_) {
int v = x_ % int(mod());
if (v < 0) {
v += mod();
}
x = v;
}
constexpr static void setMod(u32 m) {
bt = m;
}
static u32 mod() {
return bt.mod();
}
constexpr u32 val() const {
return x;
}
constexpr DynModInt operator-() const {
DynModInt res;
res.x = (x == 0 ? 0 : mod() - x);
return res;
}
constexpr DynModInt inv() const {
auto v = invGcd(x, mod());
assert(v.first == 1);
return v.second;
}
constexpr DynModInt &operator*=(const DynModInt &rhs) & {
x = bt.mul(x, rhs.val());
return *this;
}
constexpr DynModInt &operator+=(const DynModInt &rhs) & {
x += rhs.val();
if (x >= mod()) {
x -= mod();
}
return *this;
}
constexpr DynModInt &operator-=(const DynModInt &rhs) & {
x -= rhs.val();
if (x >= mod()) {
x += mod();
}
return *this;
}
constexpr DynModInt &operator/=(const DynModInt &rhs) & {
return *this *= rhs.inv();
}
friend constexpr DynModInt operator*(DynModInt lhs, const DynModInt &rhs) {
lhs *= rhs;
return lhs;
}
friend constexpr DynModInt operator+(DynModInt lhs, const DynModInt &rhs) {
lhs += rhs;
return lhs;
}
friend constexpr DynModInt operator-(DynModInt lhs, const DynModInt &rhs) {
lhs -= rhs;
return lhs;
}
friend constexpr DynModInt operator/(DynModInt lhs, const DynModInt &rhs) {
lhs /= rhs;
return lhs;
}
friend constexpr std::istream &operator>>(std::istream &is, DynModInt &a) {
i64 i;
is >> i;
a = i;
return is;
}
friend constexpr std::ostream &operator<<(std::ostream &os, const DynModInt &a) {
return os << a.val();
}
friend constexpr bool operator==(const DynModInt &lhs, const DynModInt &rhs) {
return lhs.val() == rhs.val();
}
friend constexpr std::strong_ordering operator<=>(const DynModInt &lhs, const DynModInt &rhs) {
return lhs.val() <=> rhs.val();
}
private:
u32 x;
static Barrett bt;
};
template<u32 Id>
Barrett DynModInt<Id>::bt = 998244353;
using Z = ModInt<998244353>;
struct Comb {
int n;
std::vector<Z> _fac;
std::vector<Z> _invfac;
std::vector<Z> _inv;
Comb() : n{0}, _fac{1}, _invfac{1}, _inv{0} {}
Comb(int n) : Comb() {
init(n);
}
void init(int m) {
if (m <= n) return;
_fac.resize(m + 1);
_invfac.resize(m + 1);
_inv.resize(m + 1);
for (int i = n + 1; i <= m; i++) {
_fac[i] = _fac[i - 1] * i;
}
_invfac[m] = _fac[m].inv();
for (int i = m; i > n; i--) {
_invfac[i - 1] = _invfac[i] * i;
_inv[i] = _invfac[i] * _fac[i - 1];
}
n = m;
}
Z fac(int m) {
if (m > n) init(2 * m);
return _fac[m];
}
Z invfac(int m) {
if (m > n) init(2 * m);
return _invfac[m];
}
Z inv(int m) {
if (m > n) init(2 * m);
return _inv[m];
}
Z binom(int n, int m) {
if (n < m || m < 0) return 0;
return fac(n) * invfac(m) * invfac(n - m);
}
} comb;
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int N, K;
std::cin >> N >> K;
std::vector<Z> A(N);
for (int i = 0; i < N; i++) {
std::cin >> A[i];
}
Z ans = 0;
std::vector<Z> f(K + 1);
for (int i = 0; i < N; i++) {
f[0] += 1;
for (int j = K; j >= 1; j--) {
Z p = 1;
for (int k = 1; k <= j; k++) {
p *= A[i];
f[j] += comb.binom(j, k) * p * f[j - k];
}
}
ans += f[K];
}
std::cout << ans << "\n";
return 0;
}
碎碎念,最后一个月考试月,每天最多训练3h了,至少复习9h,课程比较多,前面欠的有点多了,所以F只copy了蒋老师的代码...
下次再来补QWQ,run~

浙公网安备 33010602011771号