ZOJ Monthly, January 2018 Solution
A - Candy Game
水。
#include <bits/stdc++.h>
using namespace std; #define N 1010
int t, n;
int a[N], b[N]; int main()
{
scanf("%d", &t);
while (t--)
{
scanf("%d", &n);
for (int i = ; i <= n; ++i) scanf("%d", a + i);
for (int i = ; i <= n; ++i) scanf("%d", b + i);
puts(accumulate(a + , a + n + , ) > accumulate(b + , b + + n, ) ? "BaoBao" : "DreamGrid");
}
return ;
}
B - PreSuffix
留坑。
C - An Unsure Catch
留坑。
D - Seat Assignment
题意:给出10个数,分别表示有几个人愿意坐在编号为$i$的倍数的位置上,有m个位置,编号为1-m, 求最多坐下多少人
思路:通过暴力枚举发现在1-10的lcm2050范围内只有48种情况,网络流可以是左边十个点, 右边48个点,最大流跑一跑
#include<bits/stdc++.h> using namespace std; const int maxn = 1e4 + ;
const int INF = 0x3f3f3f3f; struct Edge{
int from;
int to;
int cap;
int flow;
Edge(){}
Edge(int from, int to, int cap, int flow) :from(from), to(to), cap(cap), flow(flow){}
}; int S, T;
vector<Edge>edge;
vector<int>G[maxn];
int arr[maxn];
int vis[maxn];
int d[maxn];
int cur[maxn];
int cnt;
int mark[maxn];
int limit[maxn];
int number[maxn]; void Init()
{
edge.clear();
for(int i = ; i < ; ++i) G[i].clear();
} void addedge(int from, int to, int cap)
{
edge.push_back(Edge(from, to, cap, ));
edge.push_back(Edge(to, from, , ));
int len = edge.size();
G[from].push_back(len - );
G[to].push_back(len - );
} bool BFS()
{
memset(d, , sizeof d);
memset(vis, , sizeof vis);
queue<int>q;
q.push(S);
d[S] = ;
vis[S] = ;
while(!q.empty())
{
int x = q.front();
q.pop();
for(int i = , len = G[x].size(); i < len; ++i)
{
Edge &e = edge[G[x][i]];
if(!vis[e.to] && e.cap > e.flow)
{
vis[e.to] = ;
d[e.to] = d[x] + ;
q.push(e.to);
}
}
}
return vis[T];
} int DFS(int x, int a)
{
if(x == T || a == ) return a;
int flow = ;
int f;
for(int &i = cur[x]; i < G[x].size(); ++i)
{
Edge &e = edge[G[x][i]];
if(d[x] + == d[e.to] && (f = DFS(e.to, min(a, e.cap - e.flow))) > )
{
e.flow += f;
edge[G[x][i] ^ ].flow -= f;
flow += f;
a -= f;
if(a == ) break;
}
}
return flow;
} int dicnic()
{
int ans = ;
while(BFS())
{
memset(cur, , sizeof cur);
ans += DFS(S, INF);
}
return ans;
} void init()
{
cnt = ;
for(int i = ; i < ; ++i)
{
int S = ;
for(int j = ; j <= ; ++j)
{
if(i % j == ) S |= ( << j);
}
if(!vis[S])
{
cnt++;
vis[S] = cnt;
number[cnt] = S;
}
mark[i] = vis[S];
}
} int main()
{
init();
int t;
scanf("%d", &t);
while(t--)
{
int n;
scanf("%d", &n);
Init();
memset(limit, , sizeof limit);
S = , T = ;
for(int i = ; i < ; ++i)
{
int num = n / ;
if(i >= && n % >= i) num++;
limit[mark[i]] += num;
}
for(int i = ; i <= ; ++i)
{
addedge(i + , T, limit[i]);
}
for(int i = ; i <= ; ++i)
{
scanf("%d", arr + i);
if(arr[i])
{
addedge(S, i, arr[i]);
for(int j = ; j <= ; ++j)
{
if(number[j] & ( << i))
{
addedge(i, j + , arr[i]);
}
}
}
}
int ans = dicnic();
printf("%d\n", ans);
}
}
E - Yet Another Data Structure Problem
题意:三种操作,一种是区间乘一个数v,一种是把区间内每个数都变成其k次方,还有一种是求区间乘积
思路:增加两个lazy操作,一种是幂次,一种是乘数
更新幂次的时候顺带把乘积更新一下
再考虑费马小定理 把幂次$模(MOD - 1)$
#include <bits/stdc++.h>
using namespace std; #define N 100010
#define ll long long
const ll MOD = (ll)1e9 + ;
int t, n, q;
ll arr[N]; ll qmod(ll base, ll n)
{
ll res = ;
while (n)
{
if (n & ) res = res * base % MOD;
base = base * base % MOD;
n >>= ;
}
return res;
} struct SEG
{
ll lazy[N << ][], mul[N << ];
void pushup(int id) { mul[id] = (mul[id << ] * mul[id << | ]) % MOD; }
void build(int id, int l, int r)
{
lazy[id][] = ; lazy[id][] = ;
if (l == r)
{
mul[id] = arr[l];
return;
}
int mid = (l + r) >> ;
build(id << , l, mid);
build(id << | , mid + , r);
pushup(id);
}
void pushdown(int id, int l, int r)
{
if (lazy[id][] != )
{
lazy[id << ][] = (lazy[id << ][] * lazy[id][]) % (MOD - );
lazy[id << ][] = qmod(lazy[id << ][], lazy[id][]);
mul[id << ] = qmod(mul[id << ], lazy[id][]);
lazy[id << | ][] = (lazy[id << | ][] * lazy[id][]) % (MOD - );
lazy[id << | ][] = qmod(lazy[id << | ][], lazy[id][]);
mul[id << | ] = qmod(mul[id << | ], lazy[id][]);
lazy[id][] = ;
}
if (lazy[id][] != )
{
int mid = (l + r) >> ;
lazy[id << ][] = (lazy[id << ][] * lazy[id][]) % MOD;
mul[id << ] = (mul[id << ] * qmod(lazy[id][], (mid - l + ))) % MOD;
lazy[id << | ][] = (lazy[id << | ][] * lazy[id][]) % MOD;
mul[id << | ] = (mul[id << | ] * qmod(lazy[id][], (r - mid))) % MOD;
lazy[id][] = ;
}
}
void update0(int id, int l, int r, int ql, int qr, ll v)
{
if (l >= ql && r <= qr)
{
lazy[id][] = (lazy[id][] * v) % MOD;
mul[id] = (mul[id] * qmod(v, (r - l + ))) % MOD;
return;
}
pushdown(id, l, r);
int mid = (l + r) >> ;
if (ql <= mid) update0(id << , l, mid, ql, qr, v);
if (qr > mid) update0(id << | , mid + , r, ql, qr, v);
pushup(id);
}
void update1(int id, int l, int r, int ql, int qr, ll v)
{
if (l >= ql && r <= qr)
{
lazy[id][] = qmod(lazy[id][], v);
mul[id] = qmod(mul[id], v);
lazy[id][] = (lazy[id][] * v) % (MOD - );
return;
}
pushdown(id, l, r);
int mid = (l + r) >> ;
if (ql <= mid) update1(id << , l, mid, ql, qr, v);
if (qr > mid) update1(id << | , mid + , r, ql, qr, v);
pushup(id);
}
ll query(int id, int l, int r, int ql, int qr)
{
if (l >= ql && r <= qr) return mul[id];
pushdown(id, l, r);
int mid = (l + r) >> ;
ll res = ;
if (ql <= mid) res = (res * query(id << , l, mid, ql, qr)) % MOD;
if (qr > mid) res = (res * query(id << | , mid + , r, ql, qr)) % MOD;
pushup(id);
return res;
}
}seg; int main()
{
scanf("%d", &t);
while (t--)
{
scanf("%d%d", &n, &q);
for (int i = ; i <= n; ++i) scanf("%lld", arr + i);
seg.build(, , n);
for (int i = , op, l, r, v; i <= q; ++i)
{
scanf("%d%d%d", &op, &l, &r);
if (op == ) printf("%lld\n", seg.query(, , n, l, r));
else
{
scanf("%d", &v);
if (op == ) seg.update0(, , n, l, r, v);
else seg.update1(, , n, l, r, v);
}
}
}
return ;
}
F - The Limit
题意:给出两个多项式,求极限
思路:四种情况,分别讨论即可。注意字符串的处理,以及最后负号的判断
#include <bits/stdc++.h>
using namespace std; #define ll long long
int t; ll x;
struct node
{
ll a[];
void scan()
{
memset(a, , sizeof a);
string s; cin >> s;
if (s[] != '-') s.insert(, "+");
while ()
{
bool flag = ;
for (int i = , len = s.size(); i < len; ++i)
{
if (s[i] == 'x' && (i == len - || s[i + ] != '^'))
{
s.insert(i + , "^1");
flag = ;
break;
}
}
if (!flag) break;
}
while ()
{
bool flag = ;
for (int i = , len = s.size(); i < len; ++i)
{
if (isdigit(s[i]) && (s[i - ] == '+' || s[i - ] == '-') && (i == len - || s[i + ] == '+' || s[i + ] == '-'))
{
s.insert(i + , "x^0");
flag = ;
break;
}
}
if (!flag) break;
}
while ()
{
bool flag = ;
for (int i = , len = s.size(); i < len; ++i)
{
if (s[i] == 'x' && !isdigit(s[i - ]))
{
s.insert(i, "");
flag = ;
break;
}
}
if (!flag) break;
}
for (int i = , len = s.size(); i < len; ++i)
{
if (s[i] == '^')
{
int pos = s[i + ] - '';
int base = (s[i - ] - '') * (s[i - ] == '+' ? : -);
a[pos] += base;
}
}
}
ll calc()
{
ll res = ;
ll base = ;
for (int i = ; i <= ; ++i, base *= x)
res += base * a[i];
return res;
}
void luo()
{
for (int i = ; i < ; ++i)
a[i] = a[i + ] * (ll)(i + );
} }fenzi, fenmu; ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; } void solve()
{
while ()
{
ll a = fenzi.calc(), b = fenmu.calc();
if (a == && b == )
{
fenzi.luo();
fenmu.luo();
}
else if (a == )
{
cout << "0\n";
return;
}
else if (b == )
{
cout << "INF\n";
return;
}
else if (a && b)
{
int vis = (a < || b < ) && !(a < && b < );
a = abs(a), b = abs(b);
ll GCD = gcd(a, b);
a /= GCD, b /= GCD;
if (vis) cout << "-";
if (b == )
cout << a << "\n";
else
cout << a << "/" << b << "\n";
return;
}
}
} int main()
{
ios::sync_with_stdio(false);
cin.tie();
cout.tie();
cin >> t;
while (t--)
{
fenzi.scan();
fenmu.scan();
cin >> x;
solve();
}
return ;
}
G - It's High Noon
留坑。
H - Traveling Plan
题意:有些城市有补给,有些没有,经过一条路要消耗这条路的边权的补给,每次询问两个补给点,需要多大容量的背包
思路:先将所有补给点作源点跑最短路,然后更新每条边权为这条边本身的边权加两个端点到最近的补给点的距离,然后求最小生成树
倍增维护最大
#include<bits/stdc++.h> using namespace std; typedef long long ll;
const ll INFLL = 0x3f3f3f3f3f3f3f3f;
const int maxn = 2e5 + ;
const int DEG = ; struct qnode{
int to;
ll val;
qnode(){}
qnode(int to, ll val) :to(to), val(val){}
bool operator < (const qnode &b) const
{
return val > b.val;
}
}; struct node{
int u, v;
ll w;
bool operator < (const node &b) const
{
return w < b.w;
}
}tmp[maxn << ]; struct Edge{
int to, nxt;
ll w;
Edge(){}
Edge(int to, int nxt, ll w) : to(to), nxt(nxt), w(w){}
}edge[maxn << ]; int n, m;
int fa[maxn][DEG];
int deg[maxn];
ll dist[maxn][DEG];
vector<qnode>G[maxn];
int vis[maxn];
int head[maxn];
ll dis[maxn];
int tot;
priority_queue<qnode>q;
int father[maxn]; void Init(int N)
{
for(int i = ; i <= N; ++i)
{
dis[i] = INFLL;
father[i] = i;
head[i] = -;
G[i].clear();
}
tot = ;
}
int find(int x)
{
return x == father[x] ? father[x] : father[x] = find(father[x]);
} bool same(int x,int y)
{
return find(x) == find(y);
} void mix(int x, int y)
{
x = find(x);
y = find(y);
if(x != y)
{
father[x] = y;
}
} void addedge(int u, int v, ll w)
{
edge[tot] = Edge(v, head[u], w); head[u] = tot++;
edge[tot] = Edge(u, head[v], w); head[v] = tot++;
} void Dijkstra()
{
while(!q.empty())
{
qnode tmp = q.top();
q.pop();
int u = tmp.to;
if(tmp.val > dis[u]) continue;
for(int i = , len = G[u].size(); i < len; ++i)
{
int v = G[u][i].to;
ll cost = G[u][i].val;
if(dis[v] > dis[u] + cost)
{
dis[v] = dis[u] + cost;
q.push(qnode(v, dis[v]));
}
}
}
} void BFS(int root)
{
queue<int>que;
deg[root] = ;
fa[root][] = root;
dist[root][] = ;
que.push(root);
while(!que.empty())
{
int tmp = que.front();
que.pop();
for(int i = ; i < DEG; ++i)
{
fa[tmp][i] = fa[fa[tmp][i - ]][i - ];
dist[tmp][i] = max(dist[tmp][i - ], dist[fa[tmp][i - ]][i - ]);
}
for(int i = head[tmp]; ~i; i = edge[i].nxt)
{
int v = edge[i].to;
if(v == fa[tmp][]) continue;
deg[v] = deg[tmp] + ;
dist[v][] = edge[i].w;
fa[v][] = tmp;
que.push(v);
}
}
} ll LCA(int u, int v)
{
ll res = ;
if(deg[u] > deg[v]) swap(u, v);
int hu = deg[u], hv = deg[v];
int tu = u, tv = v;
for(int det = hv - hu, i = ; det; det >>= , ++i)
{
if(det & )
{
res = max(res, dist[tv][i]);
tv = fa[tv][i];
}
}
if(tu == tv) return res;
for(int i = DEG - ; i >= ; --i)
{
if(fa[tu][i] == fa[tv][i]) continue;
res = max(res, dist[tu][i]);
res = max(res, dist[tv][i]);
tu = fa[tu][i];
tv = fa[tv][i];
}
return max(res, max(dist[tu][], dist[tv][]));
} int main()
{
while(~scanf("%d %d", &n, &m))
{
Init(n);
int root;
for(int i = ; i <= n; ++i)
{
scanf("%d", vis + i);
if(vis[i] == )
{
dis[i] = ;
q.push(qnode(i, ));
}
else root = i;
}
for(int i = ; i <= m; ++i)
{
scanf("%d %d %lld", &tmp[i].u, &tmp[i].v, &tmp[i].w);
G[tmp[i].u].push_back(qnode(tmp[i].v, tmp[i].w));
G[tmp[i].v].push_back(qnode(tmp[i].u, tmp[i].w));
}
Dijkstra();
// for(int i = 1; i <= n; ++i) cout << i << " " << dis[i] << endl;
for(int i = ; i <= m; ++i) tmp[i].w += dis[tmp[i].u] + dis[tmp[i].v];
sort(tmp + , tmp + + m);
for(int i = ; i <= m; ++i)
{
if(same(tmp[i].u, tmp[i].v)) continue;
mix(tmp[i].u, tmp[i].v);
addedge(tmp[i].u, tmp[i].v, tmp[i].w);
}
BFS(root);
int q;
scanf("%d", &q);
while(q--)
{
int u, v;
scanf("%d %d", &u, &v);
ll ans = LCA(u, v);
printf("%lld\n", ans);
}
}
return ;
}
I - Wooden Bridge
留坑。
J - Distance
题意:定义多维空间的距离为$\sum |a_i - b_i|^p$ 求有多少x的子串和y的子串形成的坐标的距离小于v 子串长度要相同
思路:固定x起点,双指针找y的两个端点
#include<bits/stdc++.h> using namespace std; typedef long long ll;
const int maxn = 1e3 + ; int n, p;
ll V;
ll arr[maxn], brr[maxn];
ll cnt[maxn << ], val[maxn << ]; ll calc(int i, int j)
{
ll tmp = abs(arr[i] - brr[j]);
ll res = ;
for(int i = ; i <= p; ++i) res = res * tmp;
return res;
} int main()
{
int t;
scanf("%d", &t);
while(t--)
{
scanf("%d %lld %d", &n ,&V ,&p);
memset(cnt, , sizeof cnt);
memset(val, , sizeof val);
for(int i = ; i <= n; ++i) scanf("%lld", arr + i);
for(int i = ; i <= n; ++i) scanf("%lld", brr + i);
ll ans = ;
for(int i = ; i <= n; ++i)
{
for(int j = ; j <= n; ++j)
{
int tmp = i - j + n;
cnt[tmp]++;
val[tmp] += calc(i, j);
while(cnt[tmp] > && val[tmp] > V)
{
cnt[tmp]--;
val[tmp] -= calc(i - cnt[tmp], j - cnt[tmp]);
}
ans += cnt[tmp];
}
}
printf("%lld\n", ans);
}
return ;
}
ZOJ Monthly, January 2018 Solution的更多相关文章
- ZOJ Monthly, March 2018 Solution
A - Easy Number Game 水. #include <bits/stdc++.h> using namespace std; #define ll long long #de ...
- ZOJ Monthly, January 2018 训练部分解题报告
A是水题,此处略去题解 B - PreSuffix ZOJ - 3995 (fail树+LCA) 给定多个字符串,每次询问查询两个字符串的一个后缀,该后缀必须是所有字符串中某个字符串的前缀,问该后缀最 ...
- ZOJ Monthly, January 2018
A 易知最优的方法是一次只拿一颗,石头数谁多谁赢,一样多后手赢 #include <map> #include <set> #include <ctime> #in ...
- ZOJ Monthly, June 2018 Solution
A - Peer Review Water. #include <bits/stdc++.h> using namespace std; int t, n; int main() { sc ...
- ZOJ 4010 Neighboring Characters(ZOJ Monthly, March 2018 Problem G,字符串匹配)
题目链接 ZOJ Monthly, March 2018 Problem G 题意 给定一个字符串.现在求一个下标范围$[0, n - 1]$的$01$序列$f$.$f[x] = 1$表示存在一种 ...
- ZOJ 4009 And Another Data Structure Problem(ZOJ Monthly, March 2018 Problem F,发现循环节 + 线段树 + 永久标记)
题目链接 ZOJ Monthly, March 2018 Problem F 题意很明确 这个模数很奇妙,在$[0, mod)$的所有数满足任意一个数立方$48$次对$mod$取模之后会回到本身. ...
- ZOJ Monthly, March 2018 题解
[题目链接] A. ZOJ 4004 - Easy Number Game 首先肯定是选择值最小的 $2*m$ 进行操作,这些数在操作的时候每次取一个最大的和最小的相乘是最优的. #include & ...
- matrix_2015_1 138 - ZOJ Monthly, January 2015
http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3844 第一个,n个数,每次操作最大数和最小数都变成他们的差值,最后n个数相 ...
- ZOJ Monthly, March 2018
A. Easy Number Game 贪心将第$i$小的和第$2m-i+1$小的配对即可. #include<cstdio> #include<algorithm> usin ...
随机推荐
- 【RF库Collections测试】Copy Dictionary
Name: Copy DictionarySource:Collections <test library>Arguments:[ dictionary ]Returns a copy o ...
- MUI 图标筛选切换(父页面传值子页面)
1 父页面: index.html <li class="tab_layout"> <a href="javascript:;" clas ...
- 手机QQ会员H5加速方案——sonic技术内幕
版权声明:本文由况鹰原创文章,转载请注明出处: 文章原文链接:https://www.qcloud.com/community/article/141 来源:腾云阁 https://www.qclou ...
- 旅游吧!我在这里 ——旅游相册POI搜索:找回你的足迹
版权声明:本文由林少彬原创文章,转载请注明出处: 文章原文链接:https://www.qcloud.com/community/article/89 来源:腾云阁 https://www.qclou ...
- http://www.xuexi111.com/
http://www.xuexi111.com/ http://www.minxue.net/ 拼吾爱
- struts2 中redirectAction如何传递参数!
在struts2中,初学者因为参数传递的问题往往会出现一些错误. 比如页面跳转的问题,在用户注册中,以一下代码作为案例: <struts> <constant name=" ...
- strace命令的使用
author: headsen chen date: 2018-08-28 21:25:48 跟踪一个命令的过程: [root@zabbix-test ~]# yum -y install st ...
- Add a try-catch with Mono Cecil
Adding exception handlers with Mono.Cecil is not difficult, it just requires you to know how excepti ...
- 【BZOJ4515】[Sdoi2016]游戏 树链剖分+线段树
[BZOJ4515][Sdoi2016]游戏 Description Alice 和 Bob 在玩一个游戏. 游戏在一棵有 n 个点的树上进行.最初,每个点上都只有一个数字,那个数字是 1234567 ...
- 【BZOJ2901】矩阵求和
Description 给出两个n*n的矩阵,m次询问它们的积中给定子矩阵的数值和. Input 第一行两个正整数n,m. 接下来n行,每行n个非负整数,表示第一个矩阵. 接下来n行,每行n个非负整数 ...