Replay
Problem A. I love cube
题目大意
T T T 组输入,每组一个整数 n n n.
求在 ( n − 1 ) 3 (n-1)^3 (n−1)3 的正方体中,存在多少个合法正三角形.
合法三角形:三角形的三个整顶点都在正方体内或正方体上,且三条边要至少平行于一个基平面.
1 ≤ T ≤ 1 0 5 , 1 ≤ n ≤ 1 0 18 1 \leq T \leq 10^5, 1 \leq n \leq 10^{18} 1≤T≤105,1≤n≤1018.
分析
XJ直接推了个柿子 A N S = 8 ∑ i = 1 n − 1 i 3 \begin{aligned} ANS = 8\sum_{i=1}^{n-1}{i^3} \end{aligned} ANS=8i=1∑n−1i3.
代码实现
#include <bits/stdc++.h>
using namespace std;
inline int read()
{
int x = 0, f = 1;
char ch = getchar();
while(!isdigit(ch))
{
if(ch == '-') f = -1;
ch = getchar();
}
while(isdigit(ch))
{
x = x * 10 + ch - '0';
ch = getchar();
}
return x * f;
}
typedef long long ll;
typedef unsigned long long ull;
const int M = (int)1e5;
const int N = (int)1e5;
const double eps = 1e-6;
const int inf = 0x3f3f3f3f;
const ll mod = (ll)1e9 + 7;
ll quick(ll a, ll b, ll p = mod)
{
ll s = 1;
while(b)
{
if(b & 1) s = s * a % p;
a = a * a % p;
b >>= 1;
}
return s;
}
ll inv(ll n, ll p = mod)
{
return quick(n, p - 2, p);
}
void work()
{
ll n; scanf("%lld", &n);
if(n == 1)
{
printf("0\n");
return;
}
--n;
n = n % mod;
ll ans = n * (n + 1) % mod * inv(2) % mod;
ans = ans * ans % mod;
ans = ans * 8 % mod;
printf("%lld\n", ans);
}
int main()
{
// cout << 5 * log2(inf) * (M + 2 * N) << "\n";
// freopen("input.txt", "r", stdin);
// freopen("output.txt", "w", stdout);
// ios::sync_with_stdio(0);
// cin.tie(0); cout.tie(0);
int T; scanf("%d", &T);
for(int ca = 1; ca <= T; ++ca)
{
// printf("Case #%d:\n", ca);
work();
}
// work();
// cerr << 1.0 * clock() / CLOCKS_PER_SEC << "\n";
return 0;
}
Problem B. I love tree
题目大意
n n n 个点的树, q q q 次操作,每次操作分两种.
1 a b 1 \; a \; b 1ab 表示把从点 a a a 到 点 b b b 这条链上的点加二次函数 x 2 x^2 x2.
2 a 2 \; a 2a 表示查询点 a a a 的值.
1 ≤ n , q ≤ 1 0 5 , 1 ≤ a , b ≤ n 1 \leq n, q \leq 10^5, 1 \leq a, b \leq n 1≤n,q≤105,1≤a,b≤n.
分析
显然就是树链剖分 + 区间加二次函数.
因为中间的运算结果爆掉 ll,查了 n n n 久…
代码实现
#include <bits/stdc++.h>
using namespace std;
template <typename T>
void read(T& n)
{
n = 0; int f = 1; char ch = getchar();
while(!isdigit(ch)) {if(ch == '-') f = -1; ch = getchar();}
while( isdigit(ch)) {n = n * 10 + ch - '0', ch = getchar();}
n *= f;
}
template <typename T>
void print(T n)
{
if(n < 0) putchar('-'), n = -n;
if(n > 9) print(n / 10);
putchar(n % 10 + '0');
}
template <typename T>
void print(T n, char ch)
{
print(n), putchar(ch);
}
typedef __int128 ll;
const int M = (int)1e5;
namespace TA
{
struct TA
{
int n; ll tree[M + 5];
void init(int _n) {n = _n; for(int i = 0; i <= n; ++i) tree[i] = 0;}
inline int lowbit(int n) {return n&-n;}
void add(int a, ll b) {for(int i = a; i <= n; i += lowbit(i)) tree[i] += b;}
ll ask(int r) {ll s = 0; for(int i = r; i; i -= lowbit(i)) s += tree[i]; return s;}
} t[5];
void getUpdate(ll d[], ll b[], ll len)
{
d[0] = b[0] + b[1] + b[2];
d[1] = -2 * b[0] - b[1] + b[2];
d[2] = b[0];
d[3] = -b[0] - (len + 1) * b[1] - (len + 1) * (len + 1) * b[2];
d[4] = 2 * b[0] + (2 * len + 1) * b[1] + (2ll * len * len + 2 * len - 1) * b[2];
d[5] = -b[0] - len * b[1] - len * len * b[2];
}
void add(int l, int r, ll b[])
{
ll d[6]; getUpdate(d, b, r - l + 1);
ll p[6] = {l, l + 1, l + 2, r + 1, r + 2, r + 3}, pw[6] = {1, 1, 1, 1, 1, 1};
for(int j = 1; j < 5; ++j)
{
for(int k = 0; k < 6; ++k)
{
t[j].add(p[k], pw[k] * d[k]);
pw[k] *= p[k];
}
}
}
void getQuery(ll d[], ll r)
{
d[1] = r * r * r + 6 * r * r + 11 * r + 6;
d[2] = -(3 * r * r + 12 * r + 11);
d[3] = 3 * r + 6;
d[4] = -1;
}
ll ask(int r)
{
ll d[5], s = 0; getQuery(d, r);
for(int i = 1; i < 5; ++i) s += d[i] * t[i].ask(r);
s /= 6;
return (s + t[0].ask(r));
}
ll ask(int l, int r)
{
return ask(r) - ask(l - 1);
}
}
namespace HLD
{
int cnt, head[M + 5];
struct enode
{
int v, nx;
} Edge[M * 2 + 5];
int fa[M + 5];
int sz[M + 5];
int dep[M + 5];
int son[M + 5];
int top[M + 5];
int rnk[M + 5];
int dfn[M + 5], dfnCnt;
void init(int n)
{
cnt = 0;
for(int i = 1; i <= n; ++i)
{
head[i] = -1;
}
}
void add(int u, int v)
{
Edge[cnt].v = v;
Edge[cnt].nx = head[u];
head[u] = cnt++;
}
void dfs1(int u, int f)
{
fa[u] = f, sz[u] = 1, son[u] = -1;
for(int i = head[u]; ~i; i = Edge[i].nx)
{
int v = Edge[i].v;
if(v == f) continue;
dep[v] = dep[u] + 1;
dfs1(v, u);
sz[u] += sz[v];
if(son[u] == -1 || sz[son[u]] < sz[v]) son[u] = v;
}
}
void dfs2(int u, int tp)
{
top[u] = tp, dfn[u] = ++dfnCnt, rnk[dfnCnt] = u;
if(son[u] == -1) return;
dfs2(son[u], tp);
for(int i = head[u]; ~i; i = Edge[i].nx)
{
int v = Edge[i].v;
if(v == fa[u] || v == son[u]) continue;
dfs2(v, v);
}
}
void update(int x, int y)
{
int l = 1, r = 0, xx = x, yy = y, fx = top[x], fy = top[y];
while(fx != fy)
{
if(dep[fx] > dep[fy]) r += dep[x] - dep[fx] + 1, x = fa[fx], fx = top[x];
else r += dep[y] - dep[fy] + 1, y = fa[fy], fy = top[y];
}
if(dfn[x] < dfn[y]) r += dep[y] - dep[x] + 1;
else r += dep[x] - dep[y] + 1;
x = xx, y = yy, fx = top[x], fy = top[y]; ll b[3]; int len;
while(fx != fy)
{
if(dep[fx] > dep[fy])
{
len = dep[x] - dep[fx] + 1;
b[0] = 1ll * (l + len) * (l + len);
b[1] = -2 * (l + len);
b[2] = 1;
l += len;
TA::add(dfn[fx], dfn[x], b), x = fa[fx], fx = top[x];
}
else
{
len = dep[y] - dep[fy] + 1;
b[0] = 1ll * (r - len) * (r - len);
b[1] = 2 * (r - len);
b[2] = 1;
r -= len;
TA::add(dfn[fy], dfn[y], b), y = fa[fy], fy = top[y];
}
}
if(dfn[x] < dfn[y])
{
len = dep[y] - dep[x] + 1;
b[0] = 1ll * (r - len) * (r - len);
b[1] = 2 * (r - len);
b[2] = 1;
TA::add(dfn[x], dfn[y], b);
}
else
{
len = dep[x] - dep[y] + 1;
b[0] = 1ll * (l + len) * (l + len);
b[1] = -2 * (l + len);
b[2] = 1;
TA::add(dfn[y], dfn[x], b);
}
}
}
void work()
{
int n; read(n); HLD::init(n);
for(int i = 2, u, v; i <= n; ++i)
{
read(u); read(v);
HLD::add(u, v), HLD::add(v, u);
}
HLD::dep[1] = 1;
HLD::dfs1(1, 0);
HLD::dfs2(1, 1);
for(int i = 0; i < 5; ++i) TA::t[i].init(n);
int q; read(q);
for(int i = 1, op, a, b, x; i <= q; ++i)
{
read(op);
if(op == 1)
{
read(a), read(b);
HLD::update(a, b);
}
else if(op == 2)
{
read(x);
print(TA::ask(HLD::dfn[x], HLD::dfn[x]), '\n');
}
}
}
int main()
{
// freopen("input.txt", "r", stdin);
// freopen("output.txt", "w", stdout);
work();
// cerr << 1.0 * clock() / CLOCKS_PER_SEC << "\n";
return 0;
}
Problem C. I love playing games
Problem D. I love counting
题目大意
n n n 个数 c [ 1 ] , c [ 2 ] , ⋯ , c [ n ] c[1], c[2], \cdots, c[n] c[1],c[2],⋯,c[n].
q q q 次询问,每次询问给出 l , r , a , b l, r, a, b l,r,a,b 表示询问区间 [ l , r ] [l, r] [l,r] 中有多少个不同的 c c c 满足 c ⊕ a ≤ b c \oplus a \leq b c⊕a≤b.
1 ≤ n , q ≤ 1 0 5 , 1 ≤ c [ i ] , l , r ≤ n , 1 ≤ a , b ≤ n + 1 1 \leq n, q \leq 10^5, 1 \leq c[i], l, r \leq n, 1 \leq a, b \leq n + 1 1≤n,q≤105,1≤c[i],l,r≤n,1≤a,b≤n+1.
分析
这位大佬写的很好.
又学习了求区间不同数个数和树状数组
代码实现
#include <bits/stdc++.h>
using namespace std;
template <typename T>
inline void read(T& x)
{
x = 0; int f = 1; char ch = getchar();
while(!isdigit(ch)) {if(ch == '-') f = -1; ch = getchar();}
while(isdigit(ch)) {x = x * 10 + ch - '0', ch = getchar();}
x *= f;
}
template <typename T>
void print(T x)
{
if(x < 0) putchar('-'), x = -x;
if(x > 9) print(x / 10);
putchar(x % 10 + '0');
}
template <typename T>
void print(T x, char ch)
{
print(x), putchar(ch);
}
typedef long long ll;
typedef unsigned long long ull;
const int M = (int)1e5;
const int N = (int)16;
const double eps = 1e-6;
const int inf = 0x3f3f3f3f;
const ll mod = (ll)1e9 + 7;
int n, q;
int c[M + 5];
struct qnode
{
int l, r, a, b, id;
bool operator<(const qnode& b)const
{
return r < b.r;
}
} s[M + 5];
int tot;
struct trieNode
{
int cnt, nx[2];
} trie[(N + 1) * M * 17 / 2 + 5];
int tree[M + 5];
int pre[M + 5];
int ans[M + 5];
inline int lowbit(int n)
{
return n&-n;
}
void add(int rt, int a, int b)
{
int p = rt, u;
trie[p].cnt += b;
for(int i = N; i >= 0; --i)
{
u = (a>>i&1);
if(!trie[p].nx[u]) trie[p].nx[u] = ++tot;
p = trie[p].nx[u];
trie[p].cnt += b;
}
}
int add(int p, int x)
{
for(int i = p; i <= n; i += lowbit(i)) add(tree[i], c[p], x);
}
int query(int rt, int a, int b)
{
int p = rt, ua, ub, v0, v1, ans = 0;
for(int i = N; i >= 0; --i)
{
ua = (a>>i&1), ub = (b>>i&1);
v0 = trie[p].nx[0], v1 = trie[p].nx[1];
if(!ua && !ub)
{
if(!v0 && !v1) assert(0);
else if(!v0 && v1) return ans;
else if(v0 && !v1) p = v0;
else if(v0 && v1) p = v0;
}
else if(!ua && ub)
{
if(!v0 && !v1) assert(0);
else if(!v0 && v1) p = v1;
else if(v0 && !v1) return ans += trie[v0].cnt;
else if(v0 && v1) ans += trie[v0].cnt, p = v1;
}
else if(ua && !ub)
{
if(!v0 && !v1) assert(0);
else if(!v0 && v1) p = v1;
else if(v0 && !v1) return ans;
else if(v0 && v1) p = v1;
}
else if(ua && ub)
{
if(!v0 && !v1) assert(0);
else if(!v0 && v1) return ans += trie[v1].cnt;
else if(v0 && !v1) p = v0;
else if(v0 && v1) ans += trie[v1].cnt, p = v0;
}
}
ans += trie[p].cnt;
return ans;
}
int ask(int r, int a, int b)
{
int ans = 0;
for(int i = r; i; i -= lowbit(i)) ans += query(tree[i], a, b);
return ans;
}
int query(int l, int r, int a, int b)
{
return ask(r, a, b) - ask(l - 1, a, b);
}
void work()
{
read(n);
for(int i = 1; i <= n; ++i) read(c[i]);
read(q);
for(int i = 1; i <= q; ++i) read(s[i].l), read(s[i].r), read(s[i].a), read(s[i].b), s[i].id = i;
sort(s + 1, s + q + 1);
for(int i = 1; i <= n; ++i) tree[i] = ++tot;
for(int i = 1, r = 0; i <= q; ++i)
{
while(r < s[i].r)
{
++r;
if(pre[c[r]]) add(pre[c[r]], -1);
add(r, 1);
pre[c[r]] = r;
}
ans[s[i].id] = query(s[i].l, s[i].r, s[i].a, s[i].b);
}
for(int i = 1; i <= q; ++i) print(ans[i], '\n');
}
int main()
{
// freopen("input.txt", "r", stdin);
// freopen("output.txt", "w", stdout);
// ios::sync_with_stdio(0);
// cin.tie(0); cout.tie(0);
// int T; scanf("%d", &T);
// for(int ca = 1; ca <= T; ++ca)
// {
printf("Case #%d: ", ca);
// work();
// }
work();
// cerr << 1.0 * clock() / CLOCKS_PER_SEC << "\n";
return 0;
}
Problem E. I love string
题目大意
T T T 组输入,每组输入一个整数 n n n 和长度为 n n n 的字符串 s s s.
初始字符串 t t t 为空,从前往后扫描字符串 s s s,对于当前 s [ i ] s[i] s[i],可以放到 t t t 的最前面或者放到最后面.
问在保证 t t t 的字典序最小的条件下,操作 s s s 有多少种方案.
1 ≤ T ≤ 10 , 1 ≤ n ≤ 1 0 5 1 \leq T \leq 10, 1 \leq n \leq 10^5 1≤T≤10,1≤n≤105.
分析
记字符串 s s s 的最长同字符前缀长度为 x x x,则答案为 2 x 2^x 2x.
代码实现
#include <bits/stdc++.h>
using namespace std;
inline int read()
{
int x = 0, f = 1;
char ch = getchar();
while(!isdigit(ch))
{
if(ch == '-') f = -1;
ch = getchar();
}
while(isdigit(ch))
{
x = x * 10 + ch - '0';
ch = getchar();
}
return x * f;
}
typedef long long ll;
typedef unsigned long long ull;
const int M = (int)1e5;
const int N = (int)1e5;
const double eps = 1e-6;
const int inf = 0x3f3f3f3f;
const ll mod = (ll)1e9 + 7;
int n;
char s[M + 5];
ll quick(ll a, ll b, ll p = mod)
{
ll s = 1;
while(b)
{
if(b & 1) s = s * a % p;
a = a * a % p;
b >>= 1;
}
return s;
}
void work()
{
scanf("%d", &n);
scanf("%s", s + 1);
int c = 0;
char l = s[1], r = s[1];
for(int i = 2; i <= n; ++i)
{
if(l == r && s[i] == l) ++c;
if(s[i] <= l) l = s[i];
else r = s[i];
}
printf("%lld\n", quick(2, c));
}
int main()
{
// cout << 5 * log2(inf) * (M + 2 * N) << "\n";
// freopen("input.txt", "r", stdin);
// freopen("output.txt", "w", stdout);
// ios::sync_with_stdio(0);
// cin.tie(0); cout.tie(0);
int T; scanf("%d", &T);
for(int ca = 1; ca <= T; ++ca)
{
// printf("Case #%d:\n", ca);
work();
}
// work();
// cerr << 1.0 * clock() / CLOCKS_PER_SEC << "\n";
return 0;
}
Problem G. I love data structure
Problem H. I love exam
题目大意
T T T 组输入,对于每组输入:
一个整数 n n n 表示课程总数,接下来 n n n 个字符串表示课程名.
一个整数 m m m 表示复习计划,接下来 m m m 行,每行表示复习课程名 s s s,能够提升的分数 x x x 和需要付出的时间 y y y.
最后两个整数 t t t 和 p p p 表示拥有的总时间和最多挂科数.
每门课程最高 100 100 100 分,低于 60 60 60 分为挂科.
要求在挂科数不超过 p p p 的情况下,最大化所有课程的总分数.
1 ≤ T ≤ 10 , n ≤ 50 , m ≤ 15000 , 1 ≤ x , y ≤ 10 , 1 ≤ t ≤ 500 , 0 ≤ p ≤ 3 1 \leq T \leq 10, n \leq 50, m \leq 15000, 1 \leq x, y \leq 10, 1 \leq t \leq 500, 0 \leq p \leq 3 1≤T≤10,n≤50,m≤15000,1≤x,y≤10,1≤t≤500,0≤p≤3.
分析
设 f [ i ] [ j ] f[i][j] f[i][j] 表示第 i i i 课付出了 j j j 的时间所能获得的最大分数, g [ i ] [ j ] [ k ] g[i][j][k] g[i][j][k] 表示考虑了前 i i i 门课,付出了 j j j 的时间,挂了 k k k 课的最大总分数.
转换成多重背包,每门课至多只有 100 100 100 种物品,单调队列优化可以在 O ( 100 n t ) O(100nt) O(100nt) 的时间复杂度内把 f [ i ] [ j ] f[i][j] f[i][j] 处理出来.
再对 f [ i ] [ j ] f[i][j] f[i][j] 做一遍分组背包 O ( p n t 2 ) O(pnt^2) O(pnt2) 处理出 g [ i ] [ j ] [ k ] g[i][j][k] g[i][j][k],最终答案等于 m a x 1 ≤ j ≤ t , 0 ≤ k ≤ p ( g [ n ] [ j ] [ k ] ) \begin{aligned} max_{1 \leq j \leq t, 0 \leq k \leq p}(g[n][j][k]) \end{aligned} max1≤j≤t,0≤k≤p(g[n][j][k]).
代码实现
#include <bits/stdc++.h>
using namespace std;
inline int read()
{
int x = 0, f = 1;
char ch = getchar();
while(!isdigit(ch))
{
if(ch == '-') f = -1;
ch = getchar();
}
while(isdigit(ch))
{
x = x * 10 + ch - '0';
ch = getchar();
}
return x * f;
}
typedef long long ll;
typedef unsigned long long ull;
const int M = (int)51;
const int N = (int)11;
const int O = 501;
const double eps = 1e-6;
const int inf = 0x3f3f3f3f;
const ll mod = (ll)998244353;
int n, m, t, p;
map<string, int> id;
int c[M][N][N];
int f[M][O];
int q[O + 5];
int g[M][O][4];
void init()
{
id.clear();
memset(c, 0, sizeof(c));
}
inline int calc(int i, int u, int V, int W, int k)
{
return f[i][u + k * V] - k * W;
}
void manyBag()
{
memset(f, -inf, sizeof(f));
for(int i = 1; i <= n; ++i)
{
f[i][0] = 0;
for(int V = 1; V <= 10; ++V)
{
for(int W = 1; W <= 10; ++W)
{
int C = c[i][V][W];
for(int u = 0; u < V; ++u)
{
int l = 1, r = 0;
int maxp = (t - u) / V;
for(int k = maxp - 1; k >= max(maxp - C, 0); --k)
{
while(l <= r && calc(i, u, V, W, q[r]) <= calc(i, u, V, W, k)) --r;
q[++r] = k;
}
for(int p = maxp; p >= 0; --p)
{
while(l <= r && q[l] > p - 1) ++l;
if(l <= r) f[i][u + p * V] = max(f[i][u + p * V],
calc(i, u, V, W, q[l]) + p * W);
if(p - C - 1 >= 0)
{
while(l <= r &&
calc(i, u, V, W, q[r]) <= calc(i, u, V, W, p - C - 1)) --r;
q[++r] = p - C - 1;
}
}
}
}
}
}
for(int i = 1; i <= n; ++i)
{
for(int j = 0; j <= t; ++j) f[i][j] = min(f[i][j], 100);
}
}
void groupBag()
{
memset(g, -inf, sizeof(g));
g[0][0][0] = 0;
for(int i = 1; i <= n; ++i)
{
for(int j = 0; j <= t; ++j)
{
for(int l = 0; l <= p; ++l)
{
for(int k = 0; k <= j; ++k)
{
if(l > 0 && f[i][k] < 60)
{
g[i][j][l] = max(g[i][j][l], g[i - 1][j - k][l - 1] + f[i][k]);
}
if(f[i][k] >= 60)
{
g[i][j][l] = max(g[i][j][l], g[i - 1][j - k][l] + f[i][k]);
}
}
}
}
}
}
void work()
{
init();
cin >> n;
string name;
for(int i = 1; i <= n; ++i)
{
cin >> name;
id[name] = i;
}
cin >> m;
for(int i = 1, x, y; i <= m; ++i)
{
cin >> name >> x >> y;
++c[id[name]][y][x];
}
cin >> t >> p;
manyBag();
groupBag();
int mx = -1;
for(int j = 0; j <= t; ++j)
{
for(int k = 0; k <= p; ++k) mx = max(mx, g[n][j][k]);
}
cout << mx << "\n";
}
int main()
{
// freopen("input.txt", "r", stdin);
// freopen("output.txt", "w", stdout);
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
int T; cin >> T;
for(int ca = 1; ca <= T; ++ca)
{
// printf("Case #%d:\n", ca);
work();
}
// work();
// cerr << 1.0 * clock() / CLOCKS_PER_SEC << "\n";
return 0;
}
Problem K. I love max and multiply
题目大意
T T T 组输入,每组输入一个整数 n n n 和 A [ 0 ] , A [ 1 ] , ⋯ , A [ n − 1 ] A[0], A[1], \cdots, A[n-1] A[0],A[1],⋯,A[n−1], B [ 0 ] , B [ 1 ] , ⋯ , B [ n − 1 ] B[0], B[1], \cdots, B[n - 1] B[0],B[1],⋯,B[n−1].
定义 C [ k ] = m a x ( A [ i ] × B [ j ] ) ( i & j ≥ k ) C[k] = max(A[i] \times B[j]) \; (i \& j \geq k) C[k]=max(A[i]×B[j])(i&j≥k).
求 ∑ i = 0 n − 1 C [ i ] \begin{aligned} \sum_{i=0}^{n-1}{C[i]} \end{aligned} i=0∑n−1C[i].
分析
易得 C [ k ] = m a x ( C [ k + 1 ] , A [ i ] × B [ j ] ) ( i & j = k ) C[k] = max(C[k + 1], A[i] \times B[j]) \; (i\&j = k) C[k]=max(C[k+1],A[i]×B[j])(i&j=k).
因此我们只需要求满足 i & j = k i\&j = k i&j=k 的 m a x ( A [ i ] ) , m i n ( A [ i ] ) , m a x ( B [ j ] ) , m i n ( B [ j ] ) max(A[i]), min(A[i]), max(B[j]), min(B[j]) max(A[i]),min(A[i]),max(B[j]),min(B[j]).
下面以求 m a x ( A [ i ] ) max(A[i]) max(A[i]) 为例,其余三个同理.
设 a M a x [ i B ] aMax[i_B] aMax[iB] 表示二进制状态为 i B i_B iB 时的 m a x ( A [ ] ) max(A[]) max(A[]), 二进制状态中 1 1 1 表示这一位为 1 1 1, 0 0 0 表示这一位任取.
然后按照子集决策覆盖的思想就可以把 a M a x [ ] aMax[] aMax[] 处理出来了.
代码实现
#include <bits/stdc++.h>
using namespace std;
inline int read()
{
int x = 0, f = 1;
char ch = getchar();
while(!isdigit(ch))
{
if(ch == '-') f = -1;
ch = getchar();
}
while(isdigit(ch))
{
x = x * 10 + ch - '0';
ch = getchar();
}
return x * f;
}
typedef long long ll;
typedef unsigned long long ull;
const int M = (int)3e5;
const int N = (int)18;
const double eps = 1e-6;
const int inf = 0x3f3f3f3f;
const ll mod = (ll)998244353;
int n;
int a[M + 5];
int b[M + 5];
int aMax[M + 5], aMin[M + 5];
int bMax[M + 5], bMin[M + 5];
void init()
{
memset(aMax, -inf, sizeof(aMax)), memset(aMin, inf, sizeof(aMin));
memset(bMax, -inf, sizeof(bMax)), memset(bMin, inf, sizeof(bMin));
for(int i = n - 1; i >= 0; --i)
{
aMax[i] = aMin[i] = a[i];
bMax[i] = bMin[i] = b[i];
for(int j = 0; j <= N; ++j)
{
if(!(i>>j&1) && (i|(1<<j)) < n)
{
aMax[i] = max(aMax[i], aMax[i|(1<<j)]);
aMin[i] = min(aMin[i], aMin[i|(1<<j)]);
bMax[i] = max(bMax[i], bMax[i|(1<<j)]);
bMin[i] = min(bMin[i], bMin[i|(1<<j)]);
}
}
}
}
ll c[M + 5];
void work()
{
scanf("%d", &n);
for(int i = 0; i < n; ++i) scanf("%d", &a[i]);
for(int i = 0; i < n; ++i) scanf("%d", &b[i]);
init();
c[n - 1] = 1ll * a[n - 1] * b[n - 1];
for(int i = n - 2; i >= 0; --i)
{
c[i] = c[i + 1];
c[i] = max(c[i], 1ll * aMin[i] * bMin[i]);
c[i] = max(c[i], 1ll * aMax[i] * bMax[i]);
c[i] = max(c[i], 1ll * aMax[i] * bMin[i]);
c[i] = max(c[i], 1ll * aMin[i] * bMax[i]);
// printf("c[%d] = %lld\n", i, c[i]);
}
ll s = 0;
for(int i = 0; i < n; ++i) s = (s + c[i] % mod) % mod;
s = (s % mod + mod) % mod;
printf("%lld\n", s);
}
int main()
{
// cout << 5 * log2(inf) * (M + 2 * N) << "\n";
// freopen("input.txt", "r", stdin);
// freopen("output.txt", "w", stdout);
// ios::sync_with_stdio(0);
// cin.tie(0); cout.tie(0);
int T; scanf("%d", &T);
for(int ca = 1; ca <= T; ++ca)
{
// printf("Case #%d:\n", ca);
work();
}
// work();
// cerr << 1.0 * clock() / CLOCKS_PER_SEC << "\n";
return 0;
}
Problem L. I love 114514
题目大意
签到.
分析
签到.
代码实现
#include <bits/stdc++.h>
using namespace std;
inline int read()
{
int x = 0, f = 1;
char ch = getchar();
while(!isdigit(ch))
{
if(ch == '-') f = -1;
ch = getchar();
}
while(isdigit(ch))
{
x = x * 10 + ch - '0';
ch = getchar();
}
return x * f;
}
typedef long long ll;
typedef unsigned long long ull;
const int M = (int)1e5;
const int N = (int)1e5;
const double eps = 1e-6;
const int inf = 0x3f3f3f3f;
const ll mod = (ll)998244353;
void work()
{
string s;
cin >> s;
if(s.find("114514") != string::npos) cout << "AAAAAA\n";
else cout << "Abuchulaile\n";
}
int main()
{
// cout << 5 * log2(inf) * (M + 2 * N) << "\n";
// freopen("input.txt", "r", stdin);
// freopen("output.txt", "w", stdout);
// ios::sync_with_stdio(0);
// cin.tie(0); cout.tie(0);
int T; scanf("%d", &T);
for(int ca = 1; ca <= T; ++ca)
{
// printf("Case #%d:\n", ca);
work();
}
// work();
// cerr << 1.0 * clock() / CLOCKS_PER_SEC << "\n";
return 0;
}