牛客挑战赛49
tjc的签到
ll ans = -1, w = 0;
int main() {
IOS; map<int, int> st;
cin >> n;
rep (i, 1, n) cin >> m, ++st[m];
for (auto &i : st) if (umax(ans, (ll)i.fi * i.se)) w = i.fi;
cout << ans;
return 0;
}
tjc与sweet
不考虑进位, 则每相邻10个数贡献为9(因为计数从2卡开始, 最后答案减去 0->1 的贡献)
在考虑进位, 对于10进位是 9 - 1
对于百位进位是 9 * 2 - 1
...
然后拆位统计即可
char s[N];
ll ans = -1, c = 9;
int main() {
IOS; cin >> s + 1; n = strlen(s + 1);
if (n == 1 && s[1] == '1') return cout << 0, 0;
ans += s[n] ^ '0';
for (int i = n - 1, j = 2; i; --i, ++j) {
ans = (ans + (s[i] ^ '0') * c % mod) % mod;
ll cur = (j - 1) * 9 - 1;
ans = (ans + cur * (s[i] ^ '0')) % mod;
c = (c * 10 % mod + 9 * cur % mod);
}
cout << ans;
return 0;
}
alan的DP题
很容易想到(nlogn)的可惜t飞
那只能像线性了
那就从大到小, 看 i 能不能被选呗, 并查集爬树 (O(n))
要用快读, 不然还是会t, 离谱, 1202年还有卡关同步的 cin 的
int fa[N], f[N], c[N];
ll ans;
int ff(int x) { return x == f[x] ? x : f[x] = ff(f[x]); }
int main() {
read(n, m);
rep (i, 1, n) read(fa[i]), f[i] = i;
rep (i, 1, m) read(k), ++c[k];
per (i, n, 1) {
int x = ff(i);
while (x && !c[x]) f[x] = fa[x], x = fa[x];
if (c[x]) ans += i, --c[x];
}
write(ans);
return 0;
}
alan的字符串
对于串s, t分别建立其正反的序列自动机, 爆搜
int nts[N][2][26], ntt[45][2][26], ls[26];
char s[N], t[45];
void init(char *s, int n, int nt[][2][26]) {
memset(ls, -1, sizeof ls);
per (i, n, 0) {
rep (j, 0, 25) nt[i][0][j] = ls[j];
if (i) ls[s[i] - 'a'] = i;
}
memset(ls, -1, sizeof ls);
rep (i, 1, n + 1) {
rep (j, 0, 25) nt[i][1][j] = ls[j];
if (i <= n) ls[s[i] - 'a'] = i;
}
}
void dfs(int ls, int rs, int lt, int rt, int len) {
if (min(ls, rt) == -1 || min(lt, rt) == -1) return;
if (ls >= rs || lt >= rt) {
if (ls > rs || lt > rt) umax(k, len - 2);
else if (ls == rs || lt == rt) umax(k, len - 1);
return;
}
rep (i, 0, 25) dfs(nts[ls][0][i], nts[rs][1][i], ntt[lt][0][i], ntt[rt][1][i], len + 2);
}
int main() {
IOS; cin >> s + 1 >> t + 1;
init(s, n = strlen(s + 1), nts); init(t, m = strlen(t + 1), ntt);
dfs(0, n + 1, 0, m + 1, 0);
cout << k;
return 0;
}
东兴保卫战
必须选完所有点, 故问题可以转换为, 两个的获得的边数最多,
毕竟点数确定了, 获得的边数越多, 则连通块越少
则对点按照度数排序即可, 贪心取
int deg[N];
int main() {
IOS; cin >> n; int x[2] = { 0, 0 };
rep (i, 2, n) {
int u, v; cin >> u >> v;
++deg[u], ++deg[v];
}
sort(deg + 1, deg + 1 + n);
rep (i, 1, n) x[i & 1] += deg[i];
cout << ((n + 1 >> 1) - (x[1] >> 1) - (n >> 1) + (x[0] >> 1));
return 0;
}
alan的图
不是简单路径, 则可以从路径上任意一个点, 到另一个点再回来, 则可以替换路径上任意一个点
也可以选两个点(x, y), 则路径上任意一点到x回来, 再去y回来, 则路径增加两个点(x, y)
则变成了路径上要么加两个点, 要么替换一个点,
这张图为联通二分图, 两点之间可以任意到达, 则变为了, 从整张图中选点异或值最大权值问题
二分图则是同侧路径点为奇数, 异侧点路径点数为偶数
直接线性基, 然后用个小技巧
在添加每个点权值的时候都异或一个娶不到的权值(1 << 30)
再求奇数个数异或最大值的时候直接询问 askmx(1 << 30), 偶数则问 askmx(0) 即可
贪心的保证选点的奇偶性
struct XXJ {
int g[31], mx[2];
void insert(int x) {
per (i, 30, 0) if (x >> i & 1)
if (!g[i]) { g[i] = x; return; }
else x ^= g[i];
}
void askmx() {
mx[0] = K;
per (i, 30, 0) umax(mx[1], mx[1] ^ g[i]), umax(mx[0], mx[0] ^ g[i]);
mx[1] ^= K, mx[0] ^= K;
}
} xxj;
int n, m, _, k, cas;
int bas, x, y, las;
int c[N];
VI h[N];
ll ans = 0;
void dfs(int x, int col) {
c[x] = col;
for (auto &y : h[x]) if (!c[y]) dfs(y, 3 - col);
}
int main() {
IOS; cin >> n >> m >> k >> bas >> x >> y;
rep (i, 1, n) cin >> _, xxj.insert(_ ^ K);
rep (i, 1, m) { int u, v; h[u].pb(v); h[v].pb(u); }
dfs(1, 1); xxj.askmx();
rep (i, 1, k) {
x = ((ll)x * bas + las) % n + 1, y = ((ll)y * bas + las) % n + 1;
las = xxj.mx[c[x] ^ c[y]];
ans += las;
}
cout << ans;
return 0;
}