A - Hard Code
题目链接:https://vjudge.net/contest/226594#problem/A
题意
给你n, m, 把给你的字符串按顺序分成n个长度为m的字符串, 并按顺序输出
题解
签到题
#include<set>
#include<map>
#include<cmath>
#include<stack>
#include<queue>
#include<vector>
#include<string>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define fi first
#define se second
#define fio ios::sync_with_stdio(false);cin.tie(0)
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> Pii;
const int INF = 0x3f3f3f3f;
const int M = 100005;
const int MOD = 1e9 + 7;
const double pi = acos(-1);
char s[1005];
int main()
{
int T;
scanf("%d", &T);
while(T--)
{
int n, m;
string tp;
scanf("%d %d %s", &n, &m, s + 1);
for(int i = 1; i <= n * m; ++i)
{
tp += s[i];
if(i % m == 0)
{
cout << tp << endl;
tp = "";
}
}
}
return 0;
}
B - Golden Radio Base
题目链接:https://vjudge.net/contest/226594#problem/B
题意
输入一个十进制数,输出它的ϕ进制数(ϕ = (1+√5)/2)
题目给了两个关于ϕ进制数的提示
1.ϕ + 1 = ϕ^2
2. 2 ∗ ϕ^2 = ϕ^3 + 1
题解
从第一个公式得 ϕ^n + ϕ^(n-1) = ϕ^(n+1)
所以可以知道比如10(ϕ) + 1(ϕ) = 11(ϕ) => 100(ϕ)
对于11(ϕ) 一定要转化成 100(ϕ)
从第二个公式地 2 × ϕ^n = ϕ^(n + 1) + ϕ^(n - 2)
即对于1(ϕ) + 1(ϕ) = 10.01(ϕ)
知道了这些,我们就能模拟ϕ进制数的加法了
我们大胆猜测1e9的数在ϕ进制下不会超过100位,那么直接模拟就不会超时
#include<set>
#include<map>
#include<cmath>
#include<stack>
#include<queue>
#include<vector>
#include<string>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define fi first
#define se second
#define fio ios::sync_with_stdio(false);cin.tie(0)
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> Pii;
const int INF = 0x3f3f3f3f;
const int M = 100005;
const int MOD = 1e9 + 7;
const double pi = acos(-1);
int n, ans[210], b[35][210];
void change11(int* a, int x);
void change2(int* a, int x)
{
a[x] = 0;
if(a[x + 2]) change2(a, x + 2);
else
{
a[x + 2] = 1;
if(a[x + 3]) change11(a, x + 2);
//if(a[x + 1]) change11(a, x + 1);
}
if(a[x - 1]) change2(a, x - 1);
else a[x - 1] = 1;
}
void change11(int* a, int x)
{
a[x + 1] = 0;
a[x] = 0;
if(a[x - 1]) change2(a, x - 1);
else a[x - 1] = 1;
}
void add(int* a, int* b)
{
for(int i = 101; i <= 200; ++i)
{
if(a[i] && b[i]) change2(a, i);
else if(!a[i] && b[i]) a[i] = 1;
}
for(int i = 100; i >= 0; --i)
{
if(a[i] && b[i]) change2(a, i);
else if(!a[i] && b[i]) a[i] = 1;
}
for(int i = 199; i >= 0; --i)
if(a[i] && a[i + 1]) change11(a, i);
}
void init()
{
b[0][100] = 1;
for(int i = 1; i <= 31; ++i)
{
add(b[i], b[i - 1]);
add(b[i], b[i - 1]);
}
}
int main()
{
init();
while(~scanf("%d", &n))
{
memset(ans, 0, sizeof(ans));
for(int i = 0; i <= 31; ++i)
{
if((n >> i) & 1) add(ans, b[i]);
}
int q = 0, ed = 200;
for(int i = 0; i <= 200; ++i)
{
if(ans[i])
{
q = i;
break;
}
}
for(int i = 200; i >= 0; --i)
{
if(ans[i])
{
ed = i;
break;
}
}
for(int i = q; i <= ed; ++i)
{
printf("%d", ans[i]);
if(i == 100 && i != ed) printf(".");
}
puts("");
}
return 0;
}
C - Little Tiger vs. Deep Monkey
题目链接:https://vjudge.net/contest/226594#problem/C
题解
简单01背包
#include<bits/stdc++.h>
using namespace std;
const int M = 40010;
int n, a[50], t;
long long vis[M];
double p;
int main() {
cin>>t;
while (t--) {
memset(vis, 0, sizeof(vis));
cin>>n>>p;
for (int i = 0; i < n; i++)
scanf("%d", a + i);
vis[0] = 1;
for (int i = 0; i < n; i++)
for (int j = M; j >= 0; j--) if (j >= a[i]) vis[j] += vis[j - a[i]];
long long sum = 0;
for (int i = 0; i < M; i++) {
sum += vis[i];
if (sum * 1.0 / (1ll << n) >= p) {
printf("%d\n", i);
break;
}
}
}
}
D - Bathysphere
题目链接:https://vjudge.net/contest/226594#problem/D
题解:很显然,两端是一个和x有关的二次函数,那么只需要采取双指针的方式,控制两端之间的距离刚好等于 2d 2 d 就行了
坑点:
1.由于数字比较大,达到了1e9,所以在计算二次函数的最值得时候就会出问题(1e18 > 16 后几位的精度都会炸),而三分时间又会炸,所以要用long double, 而二次函数单独写一个结构体是一个比较好的处理方式。
2.身为一个要输出浮点数的几何题居然没有SPJ,不老老实实保留三位小数会wa的亲妈都不认识。
#include<bits/stdc++.h>
using namespace std;
const int N = 2e5 + 10;
long double eps = 1e-9;
int sign(long double x) {
if (fabs(x) < eps) return 0;
return x < 0 ? -1 : 1;
}
struct point {
long double x, y;
point(long double x = 0, long double y = 0): x(x), y(y) {}
void read() {
double tmpx, tmpy;
scanf("%lf%lf", &tmpx, &tmpy);
x = tmpx;
y = tmpy;
}
}p[N];
struct pow2fuction {
long double a, b, c;
pow2fuction(long double a = 0, long double b = 0, long double c = 0) :a(a), b(b), c(c) { }
long double val(long double x) {
return a * x * x + b * x + c;
}
pow2fuction operator - (const pow2fuction &rhs) const {
return pow2fuction(a - rhs.a, b - rhs.b, c - rhs.c);
}
long double mx(long double l, long double r) {
long double ret = this->val(l);
ret = max(ret, this->val(r));
long double tmp = -b / (2 * a);
if (a < 0 && l < tmp && tmp < r) ret = max(ret, this->val(tmp));
return ret;
}
};
pow2fuction cal(int pos, long double v) {
long double k = (p[pos + 1].y - p[pos].y) / (p[pos + 1].x - p[pos].x);
long double m = p[pos].y - p[pos].x * k;
long double tmp1 = m + p[pos].y + k * v;
long double tmp2 = v - p[pos].x;
return pow2fuction(k / 2, (tmp1 + k * tmp2) / 2, tmp1 * tmp2 / 2);
}
long double area(int pos) {return (p[pos].y + p[pos + 1].y) * (p[pos + 1].x - p[pos].x) * 0.5;}
int n, l, d, t;
int main() {
scanf("%d", &t);
while (t--) {
long double ans = 0, now = 0;
scanf("%d%d", &n, &l);
for (int i = 1; i <= n; i++) p[i].read();
scanf("%d", &d);
if (sign(d == 0)) {
for (int i = 1; i <= n; i++) ans = max(ans, p[i].x);
printf("%.3f\n", (double)ans);
continue;
}
d <<= 1;
int l = 1, r = 1;
long double nowx = 0;
while (p[r + 1].x - p[l].x < d && r + 1 <= n) now += area(r++);
if (r == n) ans = now;
while (r < n) {
long double limit = min(p[l + 1].x - nowx, p[r + 1].x - (nowx + d));
ans = max(ans, now + (cal(r, d) - cal(l, 0)).mx(nowx, nowx + limit));
nowx += limit;
if (sign(nowx - p[l + 1].x) == 0) now -= area(l++);
if (sign(nowx + d - p[r + 1].x) == 0) now += area(r++);
}
printf("%.3f\n", (double)ans / d);
}
}
E - Min-max-multiply
题目链接:https://vjudge.net/contest/226594#problem/E
F - RP problem
题目链接:https://vjudge.net/contest/226594#problem/F
题解
设每一个人的价值为x,这样我们可以得到n个方程,在不考虑加边的情况下.我们可以直接高斯消元得到分配方案或者可以判断出是否有多解, 那么现在来考虑加边的情况,我们可以发现加上一条边只会影响其中的一列,那么我们就可以在矩阵后面加上m列每一列为加上一条边的情况,然后就可以愉快的高斯消元了.
代码
//#pragma comment(linker, "/stack:200000000")
//#pragma GCC optimize("Ofast,no-stack-protector")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
//#pragma GCC optimize("unroll-loops")
#include<bits/stdc++.h>
#define fi first
#define se second
#define lson l,mid,o<<1
#define rson mid+1,r,o<<1|1
#define fio ios::sync_with_stdio(false);cin.tie(0)
using namespace std;
typedef long long LL;
typedef unsigned long long uLL;
typedef pair<int, int> P;
typedef pair<P, LL> PII;
typedef pair<LL, int> PIII;
const LL INF = 0x3f3f3f3f;
const int N = 2e5 + 10;
const int M = 3e6 + 10;
const LL mod = 1e9 + 7;
const double PI=acos(-1);
inline LL ab(LL x){return x < 0 ? -x : x;}
inline LL mm(LL x, LL p){return x >= p ? x - p : x < 0 ? x + p : x;}
struct Matrix{
int n, m, u, v;
vector<int>son[105];
double a[105][210];
double exp = 1e-9;
bool vis[105][105];
bool use[105];
int id[210];
bool flag = true;
void solve(){
read();
if(!Guass()){
puts("INF");
return ;
}
int ans = -1;
double now = a[n - 1][m];
for(int i = n; i < m; ++i){
if(a[n - 1][m] / a[n - 1][i] > now){
ans = id[i];
now = a[n - 1][m] / a[n - 1][i];
}
}
printf("%d %d\n", 1, ans);
}
void read(){
memset(a, 0, sizeof a);
scanf("%d%d", &n, &m);
for(int i = 0; i < n; ++i) son[i].clear();
memset(vis, false, sizeof vis);
for(int i = 1; i <= m; ++i){
scanf("%d%d", &u, &v);
if(u == v) continue;
if(!vis[u][v]) son[u].push_back(v), vis[u][v] = true;
}
for(int i = 0; i < n; ++i){
a[i][i] = -1.0;
for(int j = 0; j < son[i].size(); ++j){
u = son[i][j];
a[u][i] = 1.0 / (son[i].size());
}
}
for(int i = 0; i < n; ++i) a[n - 1][i] = 1.0;
memset(use, false, sizeof use);
for(int i = 0; i < son[n - 1].size(); ++i) use[son[n - 1][i]] = true;
m = n;
for(int i = 0; i < n - 1; ++i){
if(!use[i]){
a[i][m] = 1.0 / (son[n - 1].size() + 1);
for(auto it : son[n - 1]) a[it][m] = 1.0 / (son[n - 1].size() + 1);
a[n - 1][m] = 1;
id[m] = i;
++m;
}
}
a[n - 1][m] = 1.0;
// pri();
}
void swap_line(int x, int y){
for(int j = 0; j <= m; ++j) swap(a[x][j], a[y][j]);
}
void pri(){
for(int i = 0; i < n; ++i) for(int j = 0; j <= m; ++j) printf("%.6f%c", a[i][j], " \n"[j == m]);
for(int i = 0; i <= m; ++i) printf("%d%c", id[i], " \n"[i == m]);
}
bool Guass(){
// printf("%d %d\n", n, m);
for(int j = 0; j < n; ++j){
int r = j;
for(int i = j + 1; i < n; ++i) if(fabs(a[i][j]) > fabs(a[r][j])) r = i;
if(fabs(a[r][j]) < exp) return 0;
if(r != j) swap_line(r, j);
for(int i = j + 1; i <= m; ++i) a[j][i] /= a[j][j];
a[j][j] = 1.0;
for(int i = j + 1; i < n; ++i){
double l = a[i][j];//if(i == 13 && j == 0) printf("%.9f %.9f\n", l, a[i][j]);
if(fabs(l) < exp) continue;
for(int k = j; k <= m; ++k){
// if(i == 13 && k == 0) printf("%.9f, %.9f, %.9f\n", a[i][k], l, a[j][k]);
a[i][k] -= l * a[j][k];
}
}
}
// pri();
// for(int i = 0; i < n; ++i) for(int j = 0; j < i; ++j) if(fabs(a[i][j]) > exp) printf("----%d %d %.9f\n", i, j, a[i][j]);
return true;
}
}mmm;
int main()
{
int t;
scanf("%d", &t);
while(t--){
mmm.solve();
}
return 0;
}
G - Mosaic
题目链接:https://vjudge.net/contest/226594#problem/G
题解:一个矩阵,然后询问其中子矩阵内的最大值,最小值,并用这两个数的平均数去更新子矩阵的中心。二维线段树的板子题,写的时候注意点是在外面那层线段树的push_up上
1.在build的时候,需要将当前节点对应的整棵线段树都push_up了
2.在update的时候,只需要将对当前这棵树所涉及到的那条链push_up了
#include<bits/stdc++.h>
#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
using namespace std;
const int N = 805;
int n, T, q, x, y, l, icase;
struct seg_tree {
int treema[N << 2], treemi[N << 2];
void build(int l, int r, int rt) {
if (l == r) {
scanf("%d", &treema[rt]);
treemi[rt] = treema[rt];
return;
}
int mid = (l + r) >> 1;
build(lson);
build(rson);
treema[rt] = max(treema[rt << 1], treema[rt << 1 | 1]);
treemi[rt] = min(treemi[rt << 1], treemi[rt << 1 | 1]);
}
void update(int l, int r, int rt, int k, int val) {
if (l == r) {
treema[rt] = treemi[rt] = val;
return;
}
int mid = (l + r) >> 1;
if (k <= mid) update(lson, k, val);
else update(rson, k, val);
treema[rt] = max(treema[rt << 1], treema[rt << 1 | 1]);
treemi[rt] = min(treemi[rt << 1], treemi[rt << 1 | 1]);
}
int query(int l, int r, int rt, int L, int R, int op) {
if (r < L || R < l) {
if (op == 1) return 0;
else return (int)2e9;
}
if (L <= l && r <= R) {
if (op == 1) return treema[rt];
else return treemi[rt];
}
int mid = (l + r) >> 1;
if (op == 1) return max(query(lson, L, R, op), query(rson, L, R, op));
else return min(query(lson, L, R, op), query(rson, L, R, op));
}
};
seg_tree sst[N << 2];
void push_up(int l, int r, int rt, int xid) {
sst[xid].treema[rt] = max(sst[xid << 1].treema[rt], sst[xid << 1 | 1].treema[rt]);
sst[xid].treemi[rt] = min(sst[xid << 1].treemi[rt], sst[xid << 1 | 1].treemi[rt]);
if (l == r) return;
int mid = (l + r) >> 1;
push_up(lson, xid);
push_up(rson, xid);
}
void build(int l, int r, int rt) {
if (l == r) {
sst[rt].build(1, n, 1);
return;
}
int mid = (l + r) >> 1;
build(lson);
build(rson);
push_up(1, n, 1, rt);
}
void push_up(int l, int r, int rt, int xid, int pos) {
sst[xid].treema[rt] = max(sst[xid << 1].treema[rt], sst[xid << 1 | 1].treema[rt]);
sst[xid].treemi[rt] = min(sst[xid << 1].treemi[rt], sst[xid << 1 | 1].treemi[rt]);
if (l == r) return;
int mid = (l + r) >> 1;
if(pos <= mid)push_up(lson, xid, pos);
else push_up(rson, xid, pos);
}
void update(int l, int r, int rt, int xpos, int ypos, int val) {
if (l == r) {
sst[rt].update(1, n, 1, ypos, val);
return;
}
int mid = (l + r) >> 1;
if (xpos <= mid) update(lson, xpos, ypos, val);
else update(rson, xpos, ypos, val);
push_up(1, n, 1, rt, ypos);
}
int query(int l, int r, int rt, int xl, int xr, int yl, int yr, int op) {
if (xr < l || r < xl) {
if (op == 1) return 0;
else return (int)2e9;
}
if (xl <= l && r <= xr) {
return sst[rt].query(1, n, 1, yl, yr, op);
}
int mid = (l + r) >> 1;
if (op == 1) return max(query(lson, xl, xr, yl, yr, op), query(rson, xl, xr, yl, yr, op));
else return min(query(lson, xl, xr, yl, yr, op), query(rson, xl, xr, yl, yr, op));
}
int main() {
scanf("%d", &T);
while (T--) {
scanf("%d", &n);
build(1, n, 1);
printf("Case #%d:\n", ++icase);
scanf("%d", &q);
while(q--) {
scanf("%d%d%d", &x, &y, &l);
int sz = l >> 1;
int num1 = query(1, n, 1, max(x - sz, 1), min(x + sz, n), max(y - sz, 1), min(y + sz, n), 1);
int num2 = query(1, n, 1, max(x - sz, 1), min(x + sz, n), max(y - sz, 1), min(y + sz, n), 2);
printf("%d\n", (num1 + num2) / 2);
update(1, n, 1, x, y, (num1 + num2) / 2);
}
}
}
H - Tower
题目链接:https://vjudge.net/contest/226594#problem/H
I - String
题目链接:https://vjudge.net/contest/226594#problem/I
题解
字符串hash, 然后暴力的枚举每一个结束位置,用一个map去存当前长度为l的串是否出现过,如果出现过那么从前面开始删, 这样每一个串只会被丢进去一次删除一次.
代码
//#pragma comment(linker, "/stack:200000000")
//#pragma GCC optimize("Ofast,no-stack-protector")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
//#pragma GCC optimize("unroll-loops")
#include<bits/stdc++.h>
#define fi first
#define se second
#define lson l,mid,o<<1
#define rson mid+1,r,o<<1|1
#define fio ios::sync_with_stdio(false);cin.tie(0)
using namespace std;
typedef long long LL;
typedef unsigned long long uLL;
typedef pair<int, int> P;
typedef pair<P, LL> PII;
typedef pair<LL, int> PIII;
const LL INF = 0x3f3f3f3f;
const int N = 3e5 + 10;
const int M = 3e6 + 10;
const LL mod = 998244353;
const double PI=acos(-1);
inline LL ab(LL x){return x < 0 ? -x : x;}
inline int mm(int x, int p){return x >= p ? x - p : x < 0 ? x + p : x;}
char s[N];
uLL base = 233;
uLL ba[N];
uLL ha[N];
void init(int len){
ha[0] = 1;
for(int i = 1; i <= len; ++i) ha[i] = ha[i - 1] * base + s[i] - 'a';
ba[0] = 1;
for(int i = 1; i <= len; ++i) ba[i] = ba[i - 1] * base;
}
uLL get_ha(int x, int l, int len){
return ha[l + x - 1] - ha[x - 1] * ba[l];
}
map<uLL, int>mp;
int solve(int x, int len, int m, int l){
if(m == 1) return (len - x + 1) / l;
int res = 0, tot = 0;
mp.clear();
for(int i = x, j = x; i + l - 1 <= len; i += l){
uLL now = get_ha(i, l, len);
while(mp[now]){
uLL gg = get_ha(j, l, len);
mp[gg]--;
tot--;
j += l;
}
tot++;
mp[now]++;
if(tot >= m) res++;
}
return res;
}
int main(){
int m, l;
while(~scanf("%d%d", &m, &l)){
scanf("%s", s + 1);
int len = strlen(s + 1);
init(len);
int ans = 0;
for(int i = 1; i <= l; ++i){
ans += solve(i, len, m, l);
}
printf("%d\n", ans);
}
return 0;
}
J - Tri-war
题目链接:https://vjudge.net/contest/226594#problem/J
题解
倍增的求lca,然后就是分类讨论,暴力的求出每一个点的影响范围.
代码
//#pragma comment(linker, "/stack:200000000")
//#pragma GCC optimize("Ofast,no-stack-protector")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
//#pragma GCC optimize("unroll-loops")
#include<bits/stdc++.h>
#define fi first
#define se second
#define lson l,mid,o<<1
#define rson mid+1,r,o<<1|1
#define fio ios::sync_with_stdio(false);cin.tie(0)
using namespace std;
typedef long long LL;
typedef unsigned long long uLL;
typedef pair<int, int> P;
typedef pair<P, LL> PII;
typedef pair<LL, int> PIII;
const LL INF = 0x3f3f3f3f;
const int N = 1e5 + 10;
const int M = 3e6 + 10;
const LL mod = 998244353;
const double PI=acos(-1);
inline LL ab(LL x){return x < 0 ? -x : x;}
inline int mm(int x, int p){return x >= p ? x - p : x < 0 ? x + p : x;}
int n;
int deep[N], fa[20][N], si[N];
vector<int>vc[N];
void dfs(int o, int u){
fa[0][o] = u;
for(int i = 1; i <= 19; ++i) fa[i][o] = fa[i - 1][fa[i - 1][o]];
deep[o] = deep[u] + 1;
si[o] = 1;
for(auto it : vc[o]) if(it != u) dfs(it, o), si[o] += si[it];
}
int get_lca(int x, int y){
if(deep[x] < deep[y]) swap(x, y);
int dd = deep[x] - deep[y];
for(int i = 0; dd; dd >>= 1, ++i) if(dd & 1) x = fa[i][x];
if(x == y) return y;
for(int i = 19; i >= 0; --i) if(fa[i][x] != fa[i][y]) x = fa[i][x], y = fa[i][y];
return fa[0][x];
}
int up(int x, int dd){
for(int i = 0; dd; dd >>= 1, ++i) if(dd & 1) x = fa[i][x];
return x;
}
int solve(int x, int y, int z){
int lca1 = get_lca(x, y), lca2 = get_lca(x, z);
int len1 = deep[x] + deep[y] - 2 * deep[lca1];
int len2 = deep[x] + deep[z] - 2 * deep[lca2];
bool flag1 = false, flag2 = false;
if(((len1 - 1) >> 1) < deep[x] - deep[lca1] && x != lca1) flag1 = true;
if(((len2 - 1) >> 1) < deep[x] - deep[lca2] && x != lca2) flag2 = true;
if(flag1 && flag2){
int len = min((len1 - 1) >> 1, (len2 - 1) >> 1);
return si[up(x, len)];
}
else if(flag1 || flag2){
if(flag2){
swap(y, z);
swap(lca1, lca2);
swap(len1, len2);
}
int to = up(x, (len1 - 1) >> 1);
int res = si[to];
if(deep[lca2] >= deep[to])
res -= si[up(z, (len2 >> 1))];
return res;
}
else{
int lca3 = get_lca(y, z);
int to1 = up(y, len1 >> 1), to2 = up(z, len2 >> 1);
if(deep[to1] <= deep[lca3] || deep[to2] <= deep[lca3]) return n - max(si[to1], si[to2]);
else return n - si[to1] - si[to2];
}
}
int main()
{
int t;
scanf("%d", &t);
while(t--){
int u, v;
scanf("%d", &n);
for(int i = 1; i <= n; ++i) vc[i].clear();
for(int i = 1; i < n; ++i){
scanf("%d%d", &u, &v);
vc[u].push_back(v);
vc[v].push_back(u);
}
dfs(1, 1);
int q, x, y, z;
scanf("%d", &q);
while(q--){
scanf("%d%d%d", &x, &y, &z);
printf("%d %d %d\n", solve(x, y, z), solve(y, x, z), solve(z, x, y));
}
}
return 0;
}
/*
1
9
1 2
1 3
1 4
2 5
2 6
2 7
6 8
6 9
4
6 3 9
8 9 6
8 9 3
8 4 7
*/