ACM-ICPC 2018 徐州赛区网络预赛 Solution
A. Hard to prepare
题意:有n个客人做成一圈,有$2^k$种面具,对于每种面具有一种面具不能使相邻的两个人戴,共有多少种做法。
思路: 把题意转化成相邻的人不能带同种面具。总数为$(2^k)^n$,减去一对相邻的客人戴同种面具$(2^k)^{(n-1)}*C(n,1)$,其中重复了两对相邻的客人戴同种面具$(2^k)^{(n-2)}*C(n,2)$,依次容斥。
最后所有人都戴同种面具的情况额外考虑,当n是奇数时,n-1对客人相同即所有人相同。n为偶数时,n-1对客人相同时用公式有重复的一轮,所以要加上。
设t=2^k
$\sum_{i = 0}^{i = n - 1} C_n^i \cdot t^{n - 1} * (-1)^i$ (n 是奇数)
$\sum_{i = 0}^{i = n - 1} C_n^i \cdot t^{n - 1} * (-1)^i + t$ (n 是偶数)
- #include <bits/stdc++.h>
- using namespace std;
- #define ll long long
- #define N 1000010
- const ll MOD = (ll)1e9 + ;
- int t, n, k;
- ll inv[N];
- ll Bit[N];
- ll Bitt[N];
- inline void Init()
- {
- inv[] = ;
- for (int i = ; i < N; ++i) inv[i] = inv[MOD % i] * (MOD - MOD / i) % MOD;
- Bit[] = ;
- for (int i = ; i < N; ++i) Bit[i] = (Bit[i - ] * ) % MOD;
- }
- inline void init()
- {
- Bitt[] = ; ll tmp = Bit[k];
- for (int i = ; i <= n; ++i) Bitt[i] = (Bitt[i - ] * tmp) % MOD;
- }
- inline void Run()
- {
- scanf("%d", &t); Init();
- while (t--)
- {
- scanf("%d%d", &n, &k);
- if (k == )
- {
- puts("");
- continue;
- }
- else if (n == )
- {
- printf("%lld\n",Bit[k]);
- continue;
- }
- init();
- ll res = ;
- ll C = ;
- for (int i = ; i < n; ++i)
- {
- res = (res + (C * Bitt[n - i] % MOD * ((i & ) ? - : ) + MOD) % MOD) % MOD;
- C = C * (n - i) % MOD * inv[i + ] % MOD;
- }
- res = (res + (Bit[k] * ((n & ) ? : )) % MOD + MOD) % MOD;
- printf("%lld\n", res);
- }
- }
- int main()
- {
- #ifdef LOCAL
- freopen("Test.in", "r", stdin);
- #endif
- Run();
- return ;
- }
B. BE, GE or NE
题意:每一轮有三种操作, 加上a 减去b 或者 取负 当且仅当 a, b, c 不为0时,对应的操作有效,给出一个上界和一个下界 大于等于上界就是 Good Ending 小于等于下界 就是 Bad Ending 否则就是 Normal Ending 两个人轮流操作,第一个人想要Good Ending 第二个人想要 Bad Ending 两个人操作最优,求最后的结局
思路:dp[i][j] 表示 第几轮 数字是多少的时候 ,记忆化爆搜 因为数字在$[-100, 100]$
- #include <bits/stdc++.h>
- using namespace std;
- typedef long long ll;
- const int MOD = (int)1e9 + ;
- const int INF = 0x3f3f3f3f;
- const ll INFLL = 0x3f3f3f3f3f3f3f3f;
- const int maxn = (int)1e3 + ;
- struct node {
- int a, b, c;
- inline node() {}
- inline node(int a, int b, int c) :a(a), b(b), c(c) {}
- }arr[maxn];
- int n, m, l, k;
- int type[maxn][maxn];//1 good 0 normal -1 bad
- int vis[maxn][maxn];
- inline void Init()
- {
- memset(vis, , sizeof vis);
- memset(type, , sizeof type);
- }
- inline int DFS(int idx, int state)
- {
- if (idx > n)
- {
- if (state <= l) return -;
- else if (state >= k) return ;
- else return ;
- }
- if (vis[idx][state]) return type[idx][state];
- vis[idx][state] = ;
- int res = ;
- //a
- int A = , B = , C = ;
- if (arr[idx].a)
- {
- A = DFS(idx + , min(, state + arr[idx].a));
- }
- //b
- if (arr[idx].b)
- {
- B = DFS(idx + , max(-, state - arr[idx].b));
- }
- //c
- if (arr[idx].c)
- {
- C = DFS(idx + , max(-, min(, state * -arr[idx].c)));
- }
- if ((A == || A == )&& (B == || B == ) && (C == || C == ) && (idx & ) == )
- {
- type[idx][state] = ;
- return ;
- }
- else if ((A == - || A == ) && (B == - || B == ) && (C == - || C == ) && (idx & ) == )
- {
- type[idx][state] = -;
- return -;
- }
- else if ((A == || B == || C == ) && (idx & ) == )
- {
- type[idx][state] = ;
- return ;
- }
- else if ((A == - || B == - || C == -) && (idx & ) == )
- {
- type[idx][state] = -;
- return -;
- }
- else
- {
- type[idx][state] = ;
- return ;
- }
- }
- inline void RUN()
- {
- while (~scanf("%d %d %d %d", &n, &m, &k, &l))
- {
- Init();
- for (int i = ; i <= n; ++i)
- {
- scanf("%d %d %d", &arr[i].a, &arr[i].b, &arr[i].c);
- }
- int ans = DFS(, m);
- if (ans == )
- {
- puts("Good Ending");
- }
- else if (ans == -)
- {
- puts("Bad Ending");
- }
- else
- {
- puts("Normal Ending");
- }
- }
- }
- int main()
- {
- #ifdef LOCAL_JUDGE
- freopen("Text.txt", "r", stdin);
- #endif // LOCAL_JUDGE
- RUN();
- #ifdef LOCAL_JUDGE
- fclose(stdin);
- #endif // LOCAL_JUDGE
- }
C. Cacti Lottery
留坑。
D. Easy Math
留坑。
E. End Fantasy VIX
留坑。
F. Features Track
水。
- #include <bits/stdc++.h>
- using namespace std;
- #define N 100010
- #define ll long long
- typedef pair <ll, ll> pii;
- int t, n, tot;
- ll ans, x, y;
- map <pii, pii> mp;
- inline void Run()
- {
- scanf("%d", &t);
- while (t--)
- {
- scanf("%d", &n); mp.clear(); ans = ;
- for (int i = ; i <= n; ++i)
- {
- scanf("%d", &tot);
- for (int j = ; j <= tot; ++j)
- {
- scanf("%lld%lld", &x, &y);
- if (mp[pii(x, y)].second == i - ) ++mp[pii(x, y)].first;
- else if (mp[pii(x, y)].second == i) continue;
- else mp[pii(x, y)].first = ;
- ans = max(ans, mp[pii(x, y)].first);
- mp[pii(x, y)].second = i;
- }
- }
- printf("%lld\n", ans);
- }
- }
- int main()
- {
- #ifdef LOCAL
- freopen("Test.in", "r", stdin);
- #endif
- Run();
- return ;
- }
G. Trace
题意:每次给出一个点,然后就会形成两条线,如果后面的矩形覆盖了前面的边,那么这条边就消失了, 最后求剩下的边是多少
思路:分别处理x轴,y轴,然后排序,然后扫过去,每次加上自己的边长以及减去标号比自己小的并且长度比自己高的个数乘自己的边长
- #include <bits/stdc++.h>
- using namespace std;
- #define N 50010
- #define ll long long
- int n;
- struct node
- {
- int l, r;
- int lazy, sum;
- inline node() {}
- inline node(int _l, int _r)
- {
- l = _l, r = _r;
- lazy = -;
- sum = ;
- }
- }tree[N << ];
- inline void pushup(int id)
- {
- tree[id].sum = tree[id << ].sum + tree[id << | ].sum;
- }
- inline void pushdown(int id)
- {
- if (tree[id].l >= tree[id].r) return;
- if (~tree[id].lazy)
- {
- int lazy = tree[id].lazy; tree[id].lazy = -;
- tree[id << ].lazy = tree[id << | ].lazy = lazy;
- tree[id << ].sum = tree[id << | ].sum = ;
- }
- }
- inline void build(int id, int l, int r)
- {
- tree[id] = node(l, r);
- if (l == r) return;
- int mid = (l + r) >> ;
- build(id << , l, mid);
- build(id << | , mid + , r);
- }
- inline void update(int id, int l, int r, int val)
- {
- if (tree[id].l >= l && tree[id].r <= r)
- {
- tree[id].sum = val;
- tree[id].lazy = val;
- return;
- }
- pushdown(id);
- int mid = (tree[id].l + tree[id].r) >> ;
- if (l <= mid) update(id << , l, r, val);
- if (r > mid) update(id << | , l, r, val);
- pushup(id);
- }
- inline int query(int id, int l, int r)
- {
- if (tree[id].l >= l && tree[id].r <= r) return tree[id].sum;
- pushdown(id);
- int mid = (tree[id].l + tree[id].r) >> ;
- int res = ;
- if (l <= mid) res += query(id << , l, r);
- if (r > mid) res += query(id << | , l, r);
- return res;
- }
- struct DT
- {
- int pos;
- ll x, y;
- inline void scan(int _pos)
- {
- pos = _pos;
- scanf("%lld%lld", &x, &y);
- }
- }arr[N];
- inline bool cmp1(DT a, DT b)
- {
- return a.x < b.x;
- }
- inline bool cmp2(DT a, DT b)
- {
- return a.y < b.y;
- }
- inline void Run()
- {
- while (scanf("%d", &n) != EOF)
- {
- for (int i = ; i <= n; ++i) arr[i].scan(i);
- build(, , n);
- sort(arr + , arr + + n, cmp1);
- ll res = ;
- for (int i = ; i <= n; ++i)
- {
- res += arr[i].y;
- int pos = query(, , arr[i].pos);
- res -= arr[i].y * pos;
- update(, , arr[i].pos, );
- update(, arr[i].pos, arr[i].pos, );
- }
- sort(arr + , arr + + n, cmp2);
- update(, , n, );
- for (int i = ; i <= n; ++i)
- {
- res += arr[i].x;
- int pos = query(, , arr[i].pos);
- res -= arr[i].x * pos;
- update(, , arr[i].pos, );
- update(, arr[i].pos, arr[i].pos, );
- }
- printf("%lld\n", res);
- }
- }
- int main()
- {
- #ifdef LOCAL
- freopen("Test.in", "r", stdin);
- #endif
- Run();
- return ;
- }
栈维护:
- #include <bits/stdc++.h>
- using namespace std;
- #define N 50010
- #define ll long long
- int n;
- struct node
- {
- int pos;
- ll x, y;
- inline void scan(int _pos)
- {
- pos = _pos;
- scanf("%lld%lld", &x, &y);
- }
- }arr[N];
- inline bool cmp1(node a, node b)
- {
- return a.x < b.x;
- }
- inline bool cmp2(node a, node b)
- {
- return a.y < b.y;
- }
- inline void Run()
- {
- while (scanf("%d", &n) != EOF)
- {
- for (int i = ; i <= n; ++i) arr[i].scan(i);
- sort(arr + , arr + + n, cmp1);
- ll res = ;
- stack<int>s;
- for (int i = ; i <= n; ++i)
- {
- res += arr[i].y;
- int cnt = ;
- while (!s.empty() && s.top() < arr[i].pos)
- {
- cnt++;
- s.pop();
- }
- res -= cnt * arr[i].y;
- s.push(arr[i].pos);
- }
- while (!s.empty())
- {
- s.pop();
- }
- sort(arr + , arr + + n, cmp2);
- for (int i = ; i <= n; ++i)
- {
- res += arr[i].x;
- int cnt = ;
- while (!s.empty() && s.top() < arr[i].pos)
- {
- cnt++;
- s.pop();
- }
- res -= cnt * arr[i].x;
- s.push(arr[i].pos);
- }
- printf("%lld\n", res);
- }
- }
- int main()
- {
- #ifdef LOCAL_JUDGE
- freopen("Text.txt", "r", stdin);
- #endif
- Run();
- return ;
- }
H. Ryuji doesn't want to study
题意:两个操作,第一种是查询$[L, R]$ 区间内 $a[L] * len + a[L + 1] * (len - 1) + ... + a[R] * 1$
第二种是改变一个数
思路:线段树,记录两个值,一个是sum,另一个是 $a[L] * len + a[L + 1] * (len - 1) + ... + a[R] * 1$
考虑合并的时候 显然两个区间合并,相当于左区间的长度增加了右区间的长度,那么只需要多加上左区间的sum * 右区间长度
- #include <bits/stdc++.h>
- using namespace std;
- #define N 100010
- #define ll long long
- int n, q;
- ll arr[N];
- struct node
- {
- int l, r;
- ll sum1, sum2;
- inline node() {}
- inline node(int l, int r, ll sum1, ll sum2) : l(l), r(r), sum1(sum1), sum2(sum2) {}
- }tree[N << ];
- inline void pushup(int id)
- {
- tree[id].sum1 = tree[id << ].sum1 + tree[id << | ].sum1;
- tree[id].sum2 = tree[id << | ].sum2 + tree[id << ].sum2 + tree[id << ].sum1 * (tree[id << | ].r - tree[id << | ].l + );
- }
- inline void build(int id, int l, int r)
- {
- tree[id] = node(l, r, , );
- if (l == r)
- {
- tree[id].sum1 = arr[tree[id].l];
- tree[id].sum2 = arr[tree[id].l];
- return;
- }
- int mid = (l + r) >> ;
- build(id << , l, mid);
- build(id << | , mid + , r);
- pushup(id);
- }
- inline void update(int id, int pos, ll val)
- {
- if (tree[id].l == tree[id].r)
- {
- tree[id].sum1 = val;
- tree[id].sum2 = val;
- return;
- }
- int mid = (tree[id].l + tree[id].r) >> ;
- if (pos <= mid) update(id << , pos, val);
- else update(id << | , pos, val);
- pushup(id);
- }
- ll anssum;
- inline void query(int id, int l, int r)
- {
- if (tree[id].l >= l && tree[id].r <= r)
- {
- anssum += tree[id].sum2 + tree[id].sum1 * (r - tree[id].r);
- return;
- }
- int mid = (tree[id].l + tree[id].r) >> ;
- if (l <= mid) query(id << , l, r);
- if (r > mid) query(id << | , l, r);
- }
- inline void Run()
- {
- while (scanf("%d%d", &n, &q) != EOF)
- {
- for (int i = ; i <= n; ++i) scanf("%lld", arr + i);
- build(, , n);
- int op, a, b; ll v;
- for (int i = ; i <= q; ++i)
- {
- scanf("%d", &op);
- if (op == )
- {
- scanf("%d%d", &a, &b);
- anssum = ; query(, a, b);
- printf("%lld\n", anssum);
- }
- else
- {
- scanf("%d%lld", &a, &v);
- update(, a, v);
- }
- }
- }
- }
- int main()
- {
- #ifdef LOCAL
- freopen("Test.in", "r", stdin);
- #endif
- Run();
- return ;
- }
I. Characters with Hash
水。
- #include <bits/stdc++.h>
- using namespace std;
- typedef long long ll;
- const int MOD = (int)1e9 + ;
- const int INF = 0x3f3f3f3f;
- const ll INFLL = 0x3f3f3f3f3f3f3f3f;
- const int maxn = (int)1e6 + ;
- int n;
- char s[];
- char str[maxn];
- int arr[maxn];
- inline void RUN()
- {
- int t;
- scanf("%d", &t);
- while (t--)
- {
- scanf("%d", &n);
- scanf("%s", s);
- scanf("%s", str);
- int len = strlen(str);
- for (int i = ; i < len; ++i)
- {
- arr[i] = abs(str[i] - s[]);
- }
- int ans = * len;
- for (int i = ; i < len; ++i)
- {
- if (arr[i] == )
- {
- ans -= ;
- }
- else if (arr[i] < )
- {
- ans -= ;
- break;
- }
- else
- {
- break;
- }
- }
- if (ans == ) ans = ;
- printf("%d\n", ans);
- }
- }
- int main()
- {
- #ifdef LOCAL_JUDGE
- freopen("Text.txt", "r", stdin);
- #endif // LOCAL_JUDGE
- RUN();
- #ifdef LOCAL_JUDGE
- fclose(stdin);
- #endif // LOCAL_JUDGE
- }
J. Maze Designer
题意:有一个$n * m$ 的迷宫,我们要建一些边使得其构成迷宫,要花费最小,然后给出两个点求最短距离
思路:花费最小,其实就是求最大生成树,那么剩下的边则为迷宫
- #include <bits/stdc++.h>
- using namespace std;
- #define N 300010
- #define ll long long
- struct Edge
- {
- int to, nx; ll w;
- inline Edge() {}
- inline Edge(int to, int nx, ll w) : to(to), nx(nx), w(w) {}
- inline bool operator < (const Edge &r) const
- {
- return w > r.w;
- }
- }edge[N << ], ed[N << ];
- int n, m, q;
- int head[N], pos, cnt, tot;
- int pre[N], F[N << ], P[N], rmq[N << ];
- ll dist[N];
- inline void Init()
- {
- memset(head, -, sizeof head); pos = ; cnt = ; dist[] = ; tot = ;
- for (int i = ; i <= n * m; ++i) pre[i] = i;
- }
- inline void addedge(int u, int v, ll w)
- {
- edge[++pos] = Edge(v, head[u], w); head[u] = pos;
- }
- struct ST
- {
- int mm[N << ];
- int dp[N << ][];
- inline void init(int n)
- {
- mm[] = -;
- for (int i = ; i <= n; ++i)
- {
- mm[i] = ((i & (i - )) == ) ? mm[i - ] + : mm[i - ];
- dp[i][] = i;
- }
- for (int j = ; j <= mm[n]; ++j)
- {
- for (int i = ; i + ( << j) - <= n; ++i)
- {
- dp[i][j] = rmq[dp[i][j - ]] < rmq[dp[i + ( << (j - ))][j - ]] ? dp[i][j - ] : dp[i + ( << (j - ))][j - ];
- }
- }
- }
- inline int query(int a, int b)
- {
- if (a > b) swap(a, b);
- int k = mm[b - a + ];
- return rmq[dp[a][k]] <= rmq[dp[b - ( << k) + ][k]] ? dp[a][k] : dp[b - ( << k) + ][k];
- }
- }st;
- inline void DFS(int u, int pre, int dep)
- {
- F[++tot] = u;
- rmq[tot] = dep;
- P[u] = tot;
- for (int it = head[u]; ~it; it = edge[it].nx)
- {
- int v = edge[it].to;
- if (v == pre) continue;
- dist[v] = dist[u] + ;
- DFS(v, u, dep + );
- F[++tot] = u;
- rmq[tot] = dep;
- }
- }
- inline void Lca_Init(int root, int node_num)
- {
- DFS(root, root, );
- st.init( * node_num - );
- }
- inline int query_lca(int u, int v)
- {
- return F[st.query(P[u], P[v])];
- }
- inline int find(int x)
- {
- if (pre[x] != x)
- pre[x] = find(pre[x]);
- return pre[x];
- }
- inline void join(int x, int y)
- {
- int fx = find(x), fy = find(y);
- if (fx != fy)
- pre[fx] = fy;
- }
- inline void Kruskal()
- {
- sort(ed + , ed + + cnt);
- int Count = ;
- for (int i = ; i <= cnt; ++i)
- {
- int u = ed[i].to, v = ed[i].nx;
- if (find(u) == find(v)) continue;
- addedge(u, v, ed[i].w); addedge(v, u, ed[i].w);
- join(u, v);
- ++Count;
- if (Count == n * m) return;
- }
- return;
- }
- inline void Run()
- {
- while (scanf("%d%d", &n, &m) != EOF)
- {
- Init();
- char dir; ll w; int u, v;
- for (int i = ; i <= n; ++i)
- {
- for (int j = ; j <= m; ++j)
- {
- for (int k = ; k < ; ++k)
- {
- scanf(" %c %lld", &dir, &w);
- u = (i - ) * n + j;
- if (dir == 'X') continue;
- if (dir == 'D') v = i * n + j;
- else if (dir == 'R') v = (i - ) * n + j + ;
- ed[++cnt] = Edge(u, v, w);
- }
- }
- }
- Kruskal(); Lca_Init(, n * m);
- int x[], y[];
- scanf("%d", &q);
- for (int i = ; i <= q; ++i)
- {
- scanf("%d%d%d%d", &x[], &y[], &x[], &y[]);
- u = (x[] - ) * n + y[], v = (x[] - ) * n + y[];
- int lca = query_lca(u, v);
- //printf("%d %d %d\n", u, v, lca);
- printf("%lld\n", dist[u] + dist[v] - * dist[lca]);
- }
- }
- }
- int main()
- {
- #ifdef LOCAL
- freopen("Test.in", "r", stdin);
- #endif
- Run();
- return ;
- }
K. Morgana Net
留坑。
ACM-ICPC 2018 徐州赛区网络预赛 Solution的更多相关文章
- ACM-ICPC 2018 徐州赛区网络预赛 G. Trace (思维,贪心)
ACM-ICPC 2018 徐州赛区网络预赛 G. Trace (思维,贪心) Trace 问答问题反馈 只看题面 35.78% 1000ms 262144K There's a beach in t ...
- ACM-ICPC 2018 徐州赛区网络预赛 J. Maze Designer (最大生成树+LCA求节点距离)
ACM-ICPC 2018 徐州赛区网络预赛 J. Maze Designer J. Maze Designer After the long vacation, the maze designer ...
- 计蒜客 1460.Ryuji doesn't want to study-树状数组 or 线段树 (ACM-ICPC 2018 徐州赛区网络预赛 H)
H.Ryuji doesn't want to study 27.34% 1000ms 262144K Ryuji is not a good student, and he doesn't wa ...
- ACM-ICPC 2018 徐州赛区网络预赛 B(dp || 博弈(未完成)
传送门 题面: In a world where ordinary people cannot reach, a boy named "Koutarou" and a girl n ...
- ACM-ICPC 2018 徐州赛区网络预赛 B. BE, GE or NE
In a world where ordinary people cannot reach, a boy named "Koutarou" and a girl named &qu ...
- ACM-ICPC 2018 徐州赛区网络预赛 H. Ryuji doesn't want to study
262144K Ryuji is not a good student, and he doesn't want to study. But there are n books he should ...
- ACM-ICPC 2018 徐州赛区网络预赛 F. Features Track
262144K Morgana is learning computer vision, and he likes cats, too. One day he wants to find the ...
- ACM-ICPC 2018 徐州赛区网络预赛 I. Characters with Hash
Mur loves hash algorithm, and he sometimes encrypt another one's name, and call him with that encryp ...
- ACM-ICPC 2018 徐州赛区网络预赛 D 杜教筛 前缀和
链接 https://nanti.jisuanke.com/t/31456 参考题解 https://blog.csdn.net/ftx456789/article/details/82590044 ...
随机推荐
- NodeJS-004-Oracle驱动编译
一.参考文章 https://community.oracle.com/docs/DOC-931127 http://www.cnblogs.com/stone_w/p/4794747.html ht ...
- Python 插件安装
0.下载Python包文件后,解压缩: 1.cd 到 插件解压缩目录,里面有setup.py的文件: 2.定位到当前目录: 3.执行:python setup.py install; 4.结束安装. ...
- 淘宝cnpm(可替代nodejs默认npm)
淘宝 NPM 镜像 这是一个完整 npmjs.org 镜像,你可以用此代替官方版本(只读),同步频率目前为 10分钟 一次以保证尽量与官方服务同步. https://npm.taobao.org/
- js常用总结
常用总结,方便大家学习共享. 1.document.write(""); 输出语句 2.JS中的注释为// 3.传统的HTML文档顺序是:document->html-& ...
- Java中实现多态的机制(实质)?
靠的是父类或接口定义的引用变量可以指向子类或具体实现类的实例对象.
- ajax返回值传给js全局变量
1. $.ajaxSetup({ async : false //设置ajax为同步方式,异步方式的话在赋值时数据还未提取出来 });var t = ""; var enginee ...
- 阿里大于短信返回XML
返回异常和成功的两种不同,XML返回直接拿alibaba_aliqin_fc_sms_num_send_response判断节点是否有这个名字 官方API地址: https://api.alidayu ...
- const T* 和 T* const
使用c++的时候,经常会在 const int *p 和 int * const p这个地方迷惑.这里记录一下: const int *p = int const *p //这里const后面的为* ...
- 【Java nio】Blocking nio2
package com.slp.nio; import org.junit.Test; import java.io.File; import java.io.IOException; import ...
- JS-元素大小深入学习-offset、client、scroll等学习研究笔记
一些属性和方法,在dom中没有规定如何确定页面中元素大小的情况下诞生... 1.偏移量(offset dimension) 测试代码: <!DOCTYPE html> <html&g ...