2017湖南多校第八场-20170429
2017-05-02 00:08
197 查看
C(1908): The Big Escape(传送门)
题意有一棵树,除了根节点,其他每个节点都有一个人,大家都要到根节点去,每条边每分钟只能有一个人通过。问最后到达的人的时间
解题思路
对于
root的每棵子树互不相关
在一棵子树中,每一秒最多只能有一个人逃出去,所以不管是哪一个子树他们每一秒只会有一个人从子树的顶点出来,所以直接求解所有子树大小的最大值就是最终答案
代码
#include <cstdio> #include <iostream> #include <fstream> #include <string> #include <cstring> using namespace std; const int MAXN = 1e5 + 5; int n, m; struct Edge{ int u, v, nxt; }E[MAXN << 1]; int Head[MAXN], tot; void edge_init(){ tot = 0; memset(Head, -1, sizeof(Head)); } void add_edge(int u, int v){ E[tot].u = u; E[tot].v = v; E[tot].nxt = Head[u]; Head[u] = tot ++; } int DFS(int u, int fa){ int ret = 1; for(int i = Head[u]; ~i;i = E[i].nxt){ if(E[i].v == fa) continue; ret += DFS(E[i].v, u); } return ret; } int main(){ int a, b, cas = 1; while(~scanf("%d%d", &n, &m)){ edge_init(); for(int i = 0;i < n - 1;i ++){ scanf("%d%d", &a, &b); add_edge(a, b); add_edge(b, a); } int ret = 0; for(int i = Head[m]; ~i;i = E[i].nxt){ ret = max(ret, DFS(E[i].v, m)); } printf("Case #%d:%d\n",cas ++, ret); } return 0; } /********************************************************************** Problem: 1908 User: 24862486 Language: C++ Result: AC Time:304 ms Memory:4436 kb **********************************************************************/
D(1909): Perfect Chocolate(传送门)
题意有一种巧克力,由黑白两种颜色的小快组成。
当黑色小块与白色小块的个数相差的绝对值不大于
1,就是一块完美巧克力
问最少切几下可以让所有的巧克力都是完美的。
解题思路
很明显最终形成的完美巧克力一定是几个
白色个数>=黑色个数,或者
黑色个数>=白色个数。因为如果形成一个白色比黑色多一个的完美巧克力和黑色比白色多一个的完美巧克力时,他们就可以合并到一起而不需要切割。
所以我们最终只要统计
1和
0的个数差就可以了。
代码
#include <cstdio> #include <cstring> #define lson l, mid, rt << 1 #define rson mid + 1, r, rt << 1 | 1 using namespace std; const int MAXN = 1e5 + 5; const int SIZE = 2e5 + 5; char S[MAXN]; int main(){ int cas = 1; while(~scanf("%s", S)){ int len = strlen(S); int sum = 0; for(int i = 0;i < len;i ++){ if(S[i] == '1') sum ++; else sum --; } if(sum < 0) sum = -sum; if(sum > 0) sum --; printf("Case #%d:%d\n",cas ++, sum); } return 0; } /********************************************************************** Problem: 1909 User: 24862486 Language: C++ Result: AC Time:12 ms Memory:1188 kb **********************************************************************/
F(1911): Card Game(传送门)
题意Alice和
Bob各有
n张卡牌,每张卡牌不超过
18种属性,他们要完成
q个任务,每次任务要求他们各拿出一张卡去组合出该任务要求的属性,问每次任务他们有多少种组合方式
解题思路
裸
fwt或模板题目,此处不多说
代码
#include <cstdio> #include <cstring> using namespace std; const int MAXN = 1 << 20; const int SIZE = 64 + 5; int A[MAXN], B[MAXN]; char op[SIZE]; void fwt(int buf[], int n){ for(int d = 1;d < n;d <<= 1){ for(int m = d << 1, i = 0;i < n;i += m){ for(int j = 0;j < d;j ++){ int x = buf[i + j], y = buf[i + j + d]; buf[i + j + d] = x + y; } } } } void ufwt(int buf[], int n){ for(int d = 1;d < n;d <<= 1){ for(int m = d << 1, i = 0;i < n;i += m){ for(int j = 0;j < d;j ++){ int x = buf[i + j], y = buf[i + j + d]; buf[i + j + d] = y - x; } } } } int toN(char buf[]){ int len =strlen(buf); int ret = 0; for(int i = 0;i < len;i ++){ ret = ret * 2 + buf[i] - '0'; } return ret; } int main(){ int _, n, m, cas = 1, Q; scanf("%d", &_); while(_ --){ scanf("%d%d", &n, &m); int tot = 1 << m; memset(A, 0, sizeof(A)); memset(B, 0, sizeof(B)); for(int i = 0;i < n;i ++){ scanf("%s", op); A[toN(op)] ++; } for(int i = 0;i < n;i ++){ scanf("%s", op); B[toN(op)] ++; } fwt(A, tot); fwt(B, tot); for(int i = 0;i < tot;i ++){ A[i] *= B[i]; } ufwt(A, tot); scanf("%d", &Q); printf("Case #%d:\n", cas ++); while(Q --){ scanf("%s", op); printf("%d\n", A[toN(op)]); } } return 0; } /********************************************************************** Problem: 1911 User: 24862486 Language: C++ Result: AC Time:140 ms Memory:9284 kb **********************************************************************/
G(1912): One Boring Problem(传送门)
题意N块钱分给
m个人,你要拿最多的,并且每个人都要有起码
1块钱
解题思路
枚举
+容斥
我们可以枚举自己拥有的钱数,然后通过容斥定理去掉那些比自己大情况就是最终答案,(当求组合数的时候使用隔板法)
代码
#include <cstdio> #include <cstring> #define lson l, mid, rt << 1 #define rson mid + 1, r, rt << 1 | 1 using namespace std; typedef long long LL; const int MAXN = 3e5 + 5; const int SIZE = 2e5 + 5; const int mod = 1e9 + 7; LL CC[MAXN]; LL CCD[MAXN]; LL mod_pow(LL x, LL n, LL p){ LL ret = 1; while(n){ if(n & 1) ret = ret * x % p; x = x * x % p; n >>= 1; } return ret; } void CC_init(){ CC[0] = CC[1] = 1; CCD[0] = 1; CCD[1] = 1; for(int i = 2;i < MAXN;i ++){ CC[i] = CC[i - 1] * i % mod; CCD[i] = mod_pow(CC[i], mod - 2, mod) % mod;//乘法逆元 } } LL C(int m, int n, LL p){ if(m > n) return 0; if(n - m < m) m = n - m; LL up = 1, down = 1; up = CC * CCD[n - m] % p; down = CCD[m]; return up * down % p; } LL lucas(int m, int n, LL p){ if(m == 0) return 1; return C(m % p, n % p, p) * lucas(m / p, n / p, p) % p; } int n, m; int main(){ CC_init(); while(~scanf("%d%d", &n, &m)){ LL ans = 0, tmp = 0; if(m == 1){ printf("1\n"); continue; } n = n - m; for(int i = 1;i <= n;i ++){ ans = (ans + lucas(m - 1 - 1, n - i + m - 1 - 1, mod)) % mod;//隔板法或者叫做插板法 //printf("[%d]\n", ans); tmp = 0; int flag = 1; for(int j = 1;j * i + i <= n && j < m;j ++){ tmp = (tmp + lucas(m - 1 - 1, n - i - j * i + m - 1 - 1, mod) * lucas(j, m - 1, mod) * flag % mod + mod) % mod; flag = - flag; } ans = (ans + mod - tmp) % mod; } printf("%lld\n", ans); } return 0; } /********************************************************************** Problem: 1912 User: 24862486 Language: C++ Result: AC Time:2348 ms Memory:5780 kb **********************************************************************/
H(1913): 一条大笨龙送礼物(传送门)
题意中文题
解题思路
二分
+线段树区间维护,将大于当前二分值的,标记为
1,否则为
0,然后进行翻转操作时,由于我们的线段树只有
1和
0两种结果,所以可以直接对一段区间赋值为
1或者
0,然后求出最终的结果,这里HDOJ5649题解链接(Round 76 1005):http://bestcoder.hdu.edu.cn/solutions.php?page=4是道类似的题目
代码
#include <cstdio> #include <cstring> #define lson l, mid, rt << 1 #define rson mid + 1, r, rt << 1 | 1 using namespace std; const int MAXN = 1e5 + 5; const int SIZE = 2e5 + 5; int Sum[MAXN * 3], Col[MAXN * 3]; int a[MAXN]; int n, m, k; struct o { int l, r; } O[MAXN]; void push_up(int rt) { Sum[rt] = Sum[rt << 1] + Sum[rt << 1 | 1]; } void push_down(int rt, int m) { if(Col[rt] != -1) { Col[rt << 1] = Col[rt << 1 | 1] = Col[rt]; Sum[rt << 1] = (m - (m >> 1)) * Col[rt]; Sum[rt << 1 | 1] = (m >> 1) * Col[rt]; Col[rt] = -1; } } void build(int lowv, int l, int r, int rt) { Col[rt] = -1; Sum[rt] = 0; if(l == r) { Sum[rt] = a[l] > lowv; return; } int mid = (l + r) >> 1; build(lowv, lson); build(lowv, rson); push_up(rt); } void update(int L, int R, int v, int l, int r, int rt) { if(L > R) return; if(L <= l && r <= R) { Sum[rt] = (r - l + 1) * v; Col[rt] = v; return ; } push_down(rt, r - l + 1); int mid = (l + r) >> 1; if(L <= mid) update(L, R, v, lson); if(R > mid) update(L, R, v, rson); push_up(rt); } int query(int L, int R, int l, int r, int rt) { if(L <= l && r <= R) { return Sum[rt]; } int mid = (l + r) >> 1; push_down(rt, r - l + 1); int ret = 0; if(L <= mid) ret += query(L, R, lson); if(R > mid) ret += query(L, R, rson); return ret; } bool C(int mid, int len) { build(mid, 1, n, 1); for(int i = 0; i < len; i ++) { int s1 = query(O[i].l, O[i].r, 1, n, 1); int s0 = O[i].r - O[i].l + 1 - s1; int cz = (s1 & 1) == 1; int qlk = s1 / 2; update(O[i].l, O[i].l + qlk - 1 + cz, 1, 1, n, 1); update(O[i].l + qlk + cz, O[i].r - qlk, 0, 1, n, 1); update(O[i].r - qlk + 1, O[i].r, 1, 1, n, 1); } return query(k, k, 1, n, 1) == 0; } int main() { while(~scanf("%d%d%d", &n, &m, &k)) { for(int i = 1; i <= n; i ++) { scanf("%d", &a[i]); } int op, len = 0, zl; for(int i = 1; i <= m; i ++) { scanf("%d", &op); if(op == 1) { scanf("%d%d", &O[len].l, &O[len].r); len ++; } else { scanf("%d", &zl); len -= zl; len = len < 0 ? 0 : len; } } //printf("[%d]\n", len); int lb = 0, ub = SIZE; while(ub - lb > 1) { int mid = (ub + lb) >> 1; if(C(mid, len)) ub = mid; else lb = mid; } printf("%d\n", ub); } return 0; } /********************************************************************** Problem: 1913 User: 24862486 Language: C++ Result: AC Time:280 ms Memory:4608 kb **********************************************************************/
HDOJ5649(传送门)
上述的类似题代码
#include <cstdio> #include <cstring> #define lson l, mid, rt << 1 #define rson mid + 1, r, rt << 1 | 1 using namespace std; const int MAXN = 1e5 + 5; const int SIZE = 64 + 5; int Sum[MAXN * 3], Col[MAXN * 3]; int a[MAXN]; int n, m, k; struct o { int op, l, r; } O[MAXN]; void push_up(int rt) { Sum[rt] = Sum[rt << 1] + Sum[rt << 1 | 1]; } void push_down(int rt, int m) { if(Col[rt] != -1) { Col[rt << 1] = Col[rt << 1 | 1] = Col[rt]; Sum[rt << 1] = (m - (m >> 1)) * Col[rt]; Sum[rt << 1 | 1] = (m >> 1) * Col[rt]; Col[rt] = -1; } } void build(int lowv, int l, int r, int rt) { Col[rt] = -1; Sum[rt] = 0; if(l == r) { Sum[rt] = a[l] > lowv; return; } int mid = (l + r) >> 1; build(lowv, lson); build(lowv, rson); push_up(rt); } void update(int L, int R, int v, int l, int r, int rt) { if(L <= l && r <= R) { Sum[rt] = (r - l + 1) * v; Col[rt] = v; return ; } push_down(rt, r - l + 1); int mid = (l + r) >> 1; if(L <= mid) update(L, R, v, lson); if(R > mid) update(L, R, v, rson); push_up(rt); } int query(int L, int R, int l, int r, int rt) { if(L <= l && r <= R) { return Sum[rt]; } int mid = (l + r) >> 1; push_down(rt, r - l + 1); int ret = 0; if(L <= mid) ret += query(L, R, lson); if(R > mid) ret += query(L, R, rson); return ret; } bool C(int lowv) { build(lowv, 1, n, 1); for(int i = 1; i <= m; i ++) { int s1 = query(O[i].l, O[i].r, 1, n, 1); int s0 = O[i].r - O[i].l + 1 - s1; if(s0 == 0 || s1 == 0) continue; if(O[i].op) { update(O[i].l, O[i].l + s1 - 1, 1, 1, n, 1); update(O[i].l + s1, O[i].r, 0, 1, n, 1); } else { update(O[i].l, O[i].l + s0 - 1, 0, 1, n, 1); update(O[i].l + s0, O[i].r, 1, 1, n, 1); } } return query(k, k, 1, n, 1) == 0; } int main() { int _; scanf("%d", &_); while(_ --) { scanf("%d%d", &n, &m); for(int i = 1; i <= n; i ++) { scanf("%d", &a[i]); } for(int i = 1; i <= m; i ++) { scanf("%d%d%d", &O[i].op, &O[i].l, &O[i].r); } scanf("%d", &k); int lb = 0, ub = n; while(ub - lb > 1) { int mid = (ub + lb) >> 1; if(C(mid)) ub = mid; else lb = mid; } printf("%d\n", ub); } return 0; }
相关文章推荐
- 2017-10-湖南套题4
- 2017湖南多校第十三场-COJ1963-Feed the rabbit
- hdu 6143: Killer Names (2017 多校第八场 1011)
- 2017湖南多校第二场-20170312
- 2017湖南多校第三场A(1025): Lawn mower
- 2017 国庆湖南Day2
- 2017 国庆湖南 Day1
- 2017湖南多校第一场-B(1002): Bones’s Battery
- 2017-10-湖南套题3
- 2017 国庆湖南 Day4
- 2017湖南多校第五场 neerc 2013 解题报告
- 2017第24届中国中西部湖南(长沙)医疗器械展览会会刊(参展商名录)
- 2017湖南多校第一场-A(1001): Assignments
- 2017湖南多校第二场-20170312
- 2017湖南多校第一场-F(1005): Federation Favorites
- hdu 6134: Battlestation Operational (2017 多校第八场 1002)【莫比乌斯】
- 2017 杭电多校赛第八场 1011题 Killer Names HDu 6143
- 2017湖南多校第一场-Generations of Tribbles
- 2017 国庆湖南 Day6
- Hybrid Crystals (2017多校 第八场) (思维题 视力题)