想了想,本来一直都是打打cf,但是没有任何记录,感觉还是记录一下cf的补题比较好
#include
using namespace std;
int main() {
int T;
cin >> T;
while (T--) {
int n, x, a, b;
cin >> n >> x >> a >> b;
if (a > b)
swap(a, b);
for (; x && a > 1; --x, --a);
for (; x && b < n; --x, ++b);
cout << b - a << '\n';
}
}
#include
#include
using namespace std;
using ll = long long;
int main() {
int T;
scanf("%d", &T);
while (T--) {
int x, y;
scanf("%d%d", &x, &y);
ll t = x;
for (int i = 1; i <= 100 && t < y; ++i) {
if (t & 1)
--t;
t = t / 2 * 3;
}
if (t >= y)
puts("YES");
else
puts("NO");
}
}
#include
#include
#include
#include
#include
#include
#include
using namespace std;
int const N = 200005;
int tot[N];
int a[N], n;
int main() {
int T;
scanf("%d", &T);
while (T--) {
scanf("%d", &n);
for (int i = 1; i <= n; ++i)
tot[i] = 0;
int ans = n + 1;
for (int i = 1; i <= n; ++i) {
scanf("%d", &a[i]);
if (tot[a[i]])
ans = min(ans, i - tot[a[i]] + 1);
tot[a[i]] = i;
}
if (ans == n + 1)
ans = -1;
printf("%d\n", ans);
}
}
#include
#include
#include
#include
#include
#include
#include
using namespace std;
using ll = long long;
using pii = pair<int, int>;
int const N = 200005;
int const LOGN = 20;
int g[N][LOGN];
int f[N];
int b[N];
pii a[N];
int n, m;
int mx[N];
int RMQ(int l, int r) {
int k = 0;
while (1 << (k + 1) <= r - l + 1)
++k;
int x = g[l][k], y = g[r - (1 << k) + 1][k];
return b[x] > b[y] ? b[x] : b[y];
}
int main() {
int T;
scanf("%d", &T);
while (T--) {
scanf("%d", &n);
for (int i = 1; i <= n; ++i)
scanf("%d", &b[i]);
scanf("%d", &m);
for (int i = 1; i <= m; ++i)
scanf("%d%d", &a[i].second, &a[i].first);
sort(a + 1, a + m + 1);
mx[m + 1] = 0;
for (int i = m; i >= 1; --i)
mx[i] = max(mx[i + 1], a[i].second);
if (mx[1] < *max_element(b + 1, b + n + 1)) {
puts("-1");
continue;
}
for (int i = 1; i <= n; ++i)
g[i][0] = i;
for (int j = 1; (1 << j) <= n; ++j)
for (int i = 1; i + (1 << j) - 1 <= n; ++i) {
int x = g[i][j - 1], y = g[i + (1 << (j - 1))][j - 1];
g[i][j] = b[x] > b[y] ? x : y;
}
for (int i = 1; i <= n; ++i) {
int l = 1, r = i - 1, pos = i;
while (l <= r) {
int mid = (l + r) >> 1;
int jud = RMQ(i - mid, i);
int p = lower_bound(a + 1, a + m + 1, pii{ mid + 1, 0 }) - a;
//cerr << "E : " << i << ' ' << mid << ' ' << jud << ' ' << p << '\n';
if (mx[p] >= jud) {
pos = i - mid;
l = mid + 1;
} else
r = mid - 1;
}
f[i] = f[pos - 1] + 1;
//cerr << ">> " << i << ' ' << pos << ' ' << f[i] << '\n';
}
printf("%d\n", f[n]);
}
}
DP,把每个位置看成分成0,1,2三组,等价于最小的代价,把序列变成递增的
#include
#include
#include
using namespace std;
int const N = 200005;
int a[N], b[N], c[N], n1, n2, n3;
int f[N][3];
int t[N];
int main() {
scanf("%d%d%d", &n1, &n2, &n3);
int n = n1 + n2 + n3;
for (int i = 1; i <= n1; ++i) {
scanf("%d", &a[i]);
t[a[i]] = 0;
}
for (int i = 1; i <= n2; ++i) {
scanf("%d", &b[i]);
t[b[i]] = 1;
}
for (int i = 1; i <= n3; ++i) {
scanf("%d", &c[i]);
t[c[i]] = 2;
}
for (int i = 1; i <= n; ++i) {
f[i][0] = f[i - 1][0] + (t[i] != 0);
f[i][1] = min(f[i - 1][0], f[i - 1][1]) + (t[i] != 1);
f[i][2] = min(min(f[i - 1][1], f[i - 1][2]), f[i - 1][0]) + (t[i] != 2);
}
int ans = min(f[n][0], min(f[n][1], f[n][2]));
printf("%d\n", ans);
}
meet-in-middle
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
int const N = 100;
void solve(map<vector<int>, int>& mp, vector<int> const& a, int m, int off) {
auto t = a;
for (int i = 0; i < (1 << m); ++i) {
for (int j = 0; j < (int)a.size(); ++j)
t[j] = __builtin_popcount(((a[j] >> off) ^ i) & ((1 << m) - 1));
int mi = *min_element(t.begin(), t.end());
for (auto& v : t)
v -= mi;
mp[t] = i << off;
}
}
void debug_(pair<vector<int>, int> const& a, pair<vector<int>, int> const& b) {
cerr << ">> " << a.second << ' ' << b.second << '\n';
cerr << "A : ";
for (auto const& v : a.first)
cerr << v << ' ';
cerr << '\n';
for (auto const& v : a.first)
cerr << __builtin_popcount(v ^ a.second) << ' ';
cerr << '\n';
cerr << "B : ";
for (auto const& v : b.first)
cerr << v << ' ';
cerr << '\n';
for (auto const& v : b.first)
cerr << __builtin_popcount(v ^ b.second) << ' ';
cerr << '\n';
}
int main() {
int n;
scanf("%d", &n);
auto a = vector<int>(n, 0);
for (auto& v : a)
scanf("%d", &v);
auto mp1 = map<vector<int>, int>();
auto mp2 = map<vector<int>, int>();
solve(mp1, a, 15, 0);
solve(mp2, a, 15, 15);
int ans = -1;
for (auto const& p : mp1) {
auto b = p.first;
auto mx = *max_element(b.begin(), b.end());
for (auto& v : b)
v = mx - v;
if (mp2.count(b)) {
//debug_(p, pair, int>{ b, mp2[b] });
ans = p.second | mp2[b];
break;
}
}
printf("%d\n", ans);
}
这题如果构建一个,首先按照素因子数量分层,最上面是素因子数量最多的数,然后每层往下面一层连边,如果下面的数是这个数的约数就连边,显然等价于找最长反链(话说我们代数学基础课的老师居然知道这个建图方式)。
然后最长反链等价于最小链覆盖,显然答案在最中间那层。(这个的证明可以考虑归纳一下,类似于证明 C ( n , p ) C(n, p) C(n,p)的最大的是 p = = n 2 p==\frac{n}{2} p==2n)
然后这个就很简单了,把每个素因子看成一个生成函数,分治NTT卷一下就好。
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
int const TT = 998244353, G = 3;
inline int KSM (int a, int k) {
int ret = 1 % TT;
for (; k; k >>= 1, a = 1ll * a * a % TT)
if (k & 1)
ret = 1ll * ret * a % TT;
return ret;
}
inline int add (int x, int y) {
if (x + y >= TT)
return x + y - TT;
else
return x + y;
}
inline int sub (int x, int y) {
if (x - y >= 0)
return x - y;
else
return x - y + TT;
}
namespace Polynom
{
vector<int> rev, rt, e = {1}, one = {1};
vector<int> operator + (vector<int> f, vector<int> g) {
int n = (int)max(f.size(), g.size());
f.resize(n);
g.resize(n);
for (int i = 0; i < n; ++i)
f[i] = add(f[i], g[i]);
return f;
}
vector<int> operator - (vector<int> f, vector<int> g) {
int n = (int)max(f.size(), g.size());
f.resize(n);
g.resize(n);
for (int i = 0; i < n; ++i)
f[i] = sub(f[i], g[i]);
return f;
}
void getRevRoot (int n) {
int m = log(n) / log(2) + 1e-7;
rev.resize(n);
rt.resize(n);
for (int i = 1; i < n; ++i)
rev[i] = rev[i >> 1] >> 1 | (i & 1) << (m - 1);
for (int len = 1, uni; len < n; len <<= 1) {
uni = KSM(G, (TT ^ 1) / (len << 1));
rt[len] = 1;
for (int i = 1; i < len; ++i)
rt[i + len] = 1ll * rt[i + len - 1] * uni % TT;
}
}
void NTT (vector<int> &f, int n) {
f.resize(n);
for (int i = 0; i < n; ++i)
if (i < rev[i])
swap(f[i], f[rev[i]]);
for (int len = 1; len < n; len <<= 1)
for (int i = 0; i < n; i += len << 1)
for (int j = 0, x, y; j < len; j++) {
x = f[i + j];
y = 1ll * f[i + j + len] * rt[j + len] % TT;
f[i + j] = add(x, y);
f[i + j + len] = sub(x, y);
}
}
vector<int> operator * (vector<int> f, vector<int> g) {
int n = 1, m = (int)f.size() + (int)g.size() - 1, ivn;
while (n < m)
n <<= 1;
ivn = KSM(n, TT - 2);
getRevRoot(n);
NTT(f, n);
NTT(g, n);
for (int i = 0; i < n; ++i)
f[i] = 1ll * f[i] * g[i] % TT;
reverse(f.begin() + 1, f.end());
NTT(f, n);
f.resize(m);
for (int i = 0; i < m; ++i)
f[i] = 1ll * f[i] * ivn % TT;
return f;
}
vector<int> polyInv (vector<int> f, int m) {
if (m == 1)
return { KSM(f[0], TT - 2) };
f.resize(m);
vector<int> g = polyInv(f, m >> 1), h;
g.resize(m);
h.resize(m);
for (int i = (m >> 1) - 1; ~i; --i)
h[i] = (g[i] << 1) % TT;
int n = m << 1, ivn = KSM(n, TT - 2);
getRevRoot(n);
NTT(f, n);
NTT(g, n);
for (int i = 0; i < n; ++i)
f[i] = 1ll * f[i] * g[i] % TT * g[i] % TT;
reverse(f.begin() + 1, f.end());
NTT(f, n);
for (int i = 0; i < m; ++i)
h[i] = sub(h[i], 1ll * f[i] * ivn % TT);
return h;
}
vector<int> operator ~ (vector<int> f) {
int n = 1, m = (int)f.size();
while (n < m)
n <<= 1;
f = polyInv(f, n);
f.resize(m);
return f;
}
vector<int> polyDeri (vector<int> f) {
if (f.empty())
return f;
int n = (int)f.size();
for (int i = 1; i < n; ++i)
f[i - 1] = 1ll * f[i] * i % TT;
f.resize(n - 1);
return f;
}
vector<int> polyInte (vector<int> f) {
int n = (int)f.size();
f.resize(n + 1);
for (int i = n; ~i; --i)
f[i] = 1ll * f[i - 1] * KSM(i, TT - 2) % TT;
return f;
}
vector<int> polyLn (vector<int> f) {
int n = (int)f.size();
f = polyInte((~f) * polyDeri(f));
f.resize(n);
return f;
}
vector<int> polyExp (vector<int> f, int n) {
if (n == 1)
return one;
f.resize(n);
vector<int> g = polyExp(f, n >> 1);
g.resize(n);
return g * (one - polyLn(g) + f);
}
inline vector<int> polyExp (vector<int> f) {
int n = 1, m = (int)f.size();
while (n < m)
n <<= 1;
f = polyExp(f, n);
f.resize(m);
return f;
}
inline vector<int> operator ^ (vector<int> f, int x) {
int n = 0, m = (int)f.size();
while (n < m - 1 && !f[n])
n++;
f.erase(f.begin(), f.begin() + n);
e = {KSM(f.empty() ? 0 : f[0], x)};
f = polyLn(f);
f.resize(n = max(0ll, m - 1ll * n * x));
for (int i = 1; i < n; ++i)
f[i] = 1ll * f[i] * x % TT;
f = polyExp(f);
reverse(f.begin(), f.end());
for (int i = m - n; i; --i)
f.push_back(0);
reverse(f.begin(), f.end());
f.resize(m);
return f;
}
inline vector<int> operator / (vector<int> f, vector<int> g) {
int n = f.size(), m = g.size();
reverse(f.begin(), f.end());
reverse(g.begin(), g.end());
f.resize(n - m + 1);
g.resize(n - m + 1);
vector<int> ret = f * (~g);
ret.resize(n - m + 1);
reverse(ret.begin(), ret.end());
return ret;
}
inline vector<int> operator % (vector<int> f, vector<int> g) {
vector<int> ret = f / g;
ret = f - (g * ret);
ret.resize(g.size() - 1);
return ret;
}
} // namespace Polynom
using namespace Polynom;
vector<int> a_mul[200000 << 2];
void getMula (vector<int> const& a, int k, int l, int r) {
if (l == r) {
a_mul[k] = vector<int>(a[l] + 1, 1);
return;
}
int mid = (l + r) >> 1;
getMula(a, k << 1, l, mid);
getMula(a, k << 1 | 1, mid + 1, r);
a_mul[k] = a_mul[k << 1] * a_mul[k << 1 | 1];
}
int main () {
int n;
scanf("%d", &n);
auto mp = map<int, int>();
for (int i = 1; i <= n; ++i) {
int x;
scanf("%d" ,&x);
mp[x]++;
}
int m = mp.size();
auto a = vector<int>();
for (auto p : mp)
a.push_back(p.second);
getMula(a, 1, 0, m - 1);
cout << a_mul[1][n / 2] << '\n';
}