【AtCoder】AGC026 题解
A - Colorful Slimes 2
找相同颜色的一段,然后答案加上段长除2下取整
代码
#include <iostream>
#include <cstdio>
using namespace std;
int N;
int a[105];
int main() {
scanf("%d",&N);
for(int i = 1 ; i <= N ; ++i) {
scanf("%d",&a[i]);
}
int ans = 0;
int cnt = 0;
for(int i = 1 ; i <= N ; ++i) {
if(a[i] != a[i - 1]) {
ans += cnt / 2;
cnt = 0;
}
++cnt;
}
ans += cnt / 2;
printf("%d\n",ans);
}
B - rng_10s
题解
如果A < B一定不可以
如果C>=B并且D>=B显然一定可以
如果D < B那么一定不可以
然后如果A大于C,那么就买几个B使得A减到C以下,如果减的过程中买不到了,那么就不可以
每次买完还需要补货的时候相当于从A开始,每次加上B和D的gcd,如果这个值落在了C和B之间,那么就不合法了
代码
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <cstring>
//#define ivorysi
#define fi first
#define se second
#define MAXN 25005
#define enter putchar('\n')
#define space putchar(' ')
typedef long long int64;
using namespace std;
template <class T>
void read(T &res) {
res = 0;char c = getchar();T f = 1;
while(c < '0' || c > '9') {
c = getchar();
if(c == '-') f = -1;
}
while(c >= '0' && c <= '9') {
res = res * 10 + c - '0';
c = getchar();
}
res *= f;
}
template <class T>
void out(T x) {
if(x < 0) {x = -x;}
if(x >= 10) {
out(x / 10);
}
putchar('0' + x % 10);
}
int T;
int64 A,B,C,D;
int64 gcd(int64 a,int64 b) {
return b == 0 ? a : gcd(b,a % b);
}
void Solve() {
read(A);read(B);read(C);read(D);
if(A < B) {puts("No");}
else {
if(C >= B && D >= B) puts("Yes");
else if(D < B) puts("No");
else {
if(A > C) {
int64 t = (A - C - 1) / B + 1;
if(t > A / B) {
puts("No");return;
}
A -= B * t;
}
int64 g = gcd(D % B,B);
if((C + 1 - A - 1) / g + 1 == (B - A - 1) / g + 1) puts("Yes");
else puts("No");
}
}
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
read(T);
while(T--) {
Solve();
}
}
C - String Coloring
题解
直接折半搜索即可
用哈希表维护前半部分拆分方式的两个字符串的哈希值
再枚举后一半的拆分方式查哈希表即可
代码
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#define enter putchar('\n')
#define space putchar(' ')
#define fi first
#define se second
#define ba 47
#define mo 999999137
#define mod 974711
//#define ivorysi
#define pii pair<int,int>
using namespace std;
typedef long long int64;
template<class T>
void read(T &res) {
res = 0;char c = getchar();T f = 1;
while(c < '0' || c > '9') {
if(c == '-') f = -1;
c = getchar();
}
while(c >= '0' && c <= '9') {
res = res * 10 + c - '0';
c = getchar();
}
res *= f;
}
template<class T>
void out(T x) {
if(x < 0) {putchar('-');x = -x;}
if(x >= 10) out(x / 10);
putchar('0' + x % 10);
}
struct Hash {
char t[20];
int64 val;
int len;
friend bool operator < (const Hash &a,const Hash &b) {
return a.val < b.val;
}
friend bool operator == (const Hash &a,const Hash &b) {
if(a.val != b.val) return false;
if(a.len != b.len) return false;
for(int i = 1 ; i <= a.len ; ++i) {
if(a.t[i] != b.t[i]) return false;
}
return true;
}
}B[1000005];
int cnt;
int64 e[55];
struct Mmp {
struct node {
int next,v;
int64 x;
}E[1000005];
int head[mod + 5],sumE;
void clear() {
memset(head,0,sizeof(head));
sumE = 0;
}
void add(int64 x,int v) {
int u = x % mod;
E[++sumE].x = x;
E[sumE].v = v;
E[sumE].next = head[u];
head[u] = sumE;
}
void Insert(int64 x) {
int u = x % mod;
for(int i = head[u] ; i ; i = E[i].next) {
if(E[i].x == x) {E[i].v++;return;}
}
add(x,1);
}
int Query(int64 x) {
int u = x % mod;
for(int i = head[u]; i ; i = E[i].next) {
if(E[i].x == x) return E[i].v;
}
return 0;
}
}M1,M2;
int64 Calc(char *s,int l) {
int64 res = 0;
for(int i = 1 ; i <= l ; ++i) {
res += (s[i] - 'a' + 1) * e[i] % mo;
res %= mo;
}
return res;
}
void Insert(char *s,int l) {
++cnt;
for(int i = 1 ; i <= l ; ++i) B[cnt].t[i] = s[i];
B[cnt].len = l;B[cnt].val = Calc(s,l);
}
int N;
char s[55];
void Solve() {
read(N);
e[0] = 1;
for(int i = 1 ; i <= N ; ++i) e[i] = e[i - 1] * ba % mo;
scanf("%s",s + 1);
char t1[25],t2[25];
int c1,c2;
for(int S = 0 ; S < (1 << N) ; ++S) {
c1 = c2 = 0;
int T = 0;
for(int i = 1 ; i <= N ; ++i) {
if(S >> (i - 1) & 1) t1[++c1] = s[i];
else {t2[++c2] = s[i];T |= (1 << i - 1);}
}
if(S > T) continue;
if(c1) Insert(t1,c1);
if(c2) Insert(t2,c2);
}
sort(B + 1,B + cnt + 1);
cnt = unique(B + 1,B + cnt + 1) - B - 1;
M1.clear();M2.clear();
for(int i = 1 ; i <= cnt ; ++i) {
M1.add(B[i].val,i);
}
for(int S = 0 ; S < (1 << N) ; ++S) {
c1 = c2 = 0;
for(int i = 1 ; i <= N ; ++i) {
if(S >> (i - 1) & 1) t1[++c1] = s[i];
else {t2[++c2] = s[i];}
}
int d1 = 0,d2 = 0;
if(c1) d1 = M1.Query(Calc(t1,c1));
if(c2) d2 = M1.Query(Calc(t2,c2));
M2.Insert(1LL * d1 * (cnt + 1) + d2);
}
int64 ans = 0;
for(int S = 0 ; S < (1 << N) ; ++S) {
c1 = c2 = 0;
for(int i = N + 1 ; i <= 2 * N ; ++i) {
if(S >> (i - N - 1) & 1) t1[++c1] = s[i];
else {t2[++c2] = s[i];}
}
reverse(t1 + 1,t1 + c1 + 1);
reverse(t2 + 1,t2 + c2 + 1);
int d1 = 0,d2 = 0;
if(c1) d1 = M1.Query(Calc(t1,c1));
if(c2) d2 = M1.Query(Calc(t2,c2));
ans += M2.Query(1LL * d1 * (cnt + 1) + d2);
}
out(ans);enter;
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
Solve();
}
D - Histogram Coloring
题解
我们考虑从上往下,对于每个分离的直方图的横列进行dp,然后再把他们合起来
我们发现,如果直方图不是10101010或0101010101的形式,那么以下所有列就只有一种放置方法
那么我们记录两个值,一个是直方图最下面一行填的是1010101或01010101,记为dp[S][1],一个是所有的方案数记为dp[S][2]
转移方法是对于一个列数一样的矩形块
dp[S][1]是它上面所有的直方图dp[S][1]乘起来,然后再乘上2的行数次幂
dp[S][2]我们认为是如果是010101或101010,那么下面对应的有两种方式,剩下的只有一种,其余的方块随便填,下面每一行是上一行取反
是上面所有直方图的(dp[T][1] + dp[T][2])乘起来,然后再乘上2的剩余方块数的幂
但是dp[S][2]也应该包括相邻两行有相同的情况,我们就再加上dp[S][1],同时减掉dp[S][1]中我们每行都不同的情况
代码
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#define enter putchar('\n')
#define space putchar(' ')
#define fi first
#define se second
#define mp make_pair
#define ba 47
#define mo 999999137
#define mod 974711
//#define ivorysi
#define pii pair<int,int>
using namespace std;
typedef long long int64;
template<class T>
void read(T &res) {
res = 0;char c = getchar();T f = 1;
while(c < '0' || c > '9') {
if(c == '-') f = -1;
c = getchar();
}
while(c >= '0' && c <= '9') {
res = res * 10 + c - '0';
c = getchar();
}
res *= f;
}
template<class T>
void out(T x) {
if(x < 0) {putchar('-');x = -x;}
if(x >= 10) out(x / 10);
putchar('0' + x % 10);
}
const int MOD = 1000000007;
int N;
int h[105];
bool vis[105];
int inc(int a,int b) {
return a + b >= MOD ? a + b - MOD : a + b;
}
int mul(int a,int b) {
return 1LL * a * b % MOD;
}
int fpow(int x,int c) {
int res = 1,t = x;
while(c) {
if(c & 1) res = mul(res,t);
t = mul(t,t);
c >>= 1;
}
return res;
}
void update(int &x,int y) {
x = inc(x,y);
}
pii Solve(int l,int r,int v) {
int minv = 1e9;
for(int i = l ; i <= r ; ++i) minv = min(minv,h[i]);
int p,cnt = 0;
pii res = mp(1,1);
for(int i = l ; i <= r ; ++i) {
if(h[i] > minv) ++cnt;
}
for(int i = l ; i <= r ; ++i) {
if(h[i] > minv) {
p = i;
while(p < r && h[p + 1] > minv) ++p;
pii f = Solve(i,p,minv);
res.fi = mul(res.fi,f.fi);
res.se = mul(res.se,inc(f.se,f.fi));
i = p;
}
}
int t = mul(res.fi,2);
res.se = mul(res.se,fpow(2,r - l + 1 - cnt));
res.fi = mul(res.fi,fpow(2,minv - v));
res.se = inc(res.se,inc(res.fi,MOD - t));
return res;
}
void Solve() {
read(N);
for(int i = 1 ; i <= N ; ++i) {read(h[i]);}
pii ans = Solve(1,N,0);
out(ans.se);enter;
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
Solve();
}
E - Synchronized Subsequence
题解
如果b在a前就一直选,选到某个最大的a的位置会更改成一段a在b前
如果这个a在b前是最后一部分就取到所有的abababab...前,否则就跳过这一段
具体就用string维护一下后缀能取到的max字符串就好了
代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cmath>
#include <queue>
#include <ctime>
#include <map>
#include <set>
#define fi first
#define se second
#define pii pair<int,int>
//#define ivorysi
#define mp make_pair
#define pb push_back
#define enter putchar('\n')
#define space putchar(' ')
#define MAXN 6005
using namespace std;
typedef long long int64;
typedef double db;
typedef unsigned int u32;
template<class T>
void read(T &res) {
res = 0;T f = 1;char c = getchar();
while(c < '0' || c > '9') {
if(c == '-') f = -1;
c = getchar();
}
while(c >= '0' && c <= '9' ) {
res = res * 10 - '0' + c;
c = getchar();
}
res *= f;
}
template<class T>
void out(T x) {
if(x < 0) {x = -x;putchar('-');}
if(x >= 10) {
out(x / 10);
}
putchar('0' + x % 10);
}
namespace task {
char s[MAXN];
int N,a[MAXN],b[MAXN],tota,totb,pos[MAXN];
string str[MAXN];
bool vis[MAXN];
void Init() {
read(N);
scanf("%s",s + 1);
tota = 0;totb = 0;
for(int i = 1 ; i <= 2 * N ; ++i) {
if(s[i] == 'a') {a[++tota] = i;pos[i] = tota;}
else {b[++totb] = i;pos[i] = totb;}
}
}
void Solve() {
str[2 * N + 1] = "";
for(int i = 2 * N ; i >= 1 ; --i) {
str[i] = max(str[i],str[i + 1]);
string t = "";
int p = pos[i];
if(s[i] == 'a' && a[p] < b[p]) {
str[i] = max(str[i],"ab" + str[b[p] + 1]);
}
else if(s[i] == 'b' && b[p] < a[p]) {
memset(vis,0,sizeof(vis));
int maxv = a[p];
for(int j = i ; j <= maxv ; ++j) {
if(s[j] == 'b') {
p = pos[j];
vis[b[p]] = 1;vis[a[p]] = 1;
maxv = max(a[p],maxv);
}
if(vis[j]) t += s[j];
}
t += str[maxv + 1];
str[i] = max(str[i],t);
}
}
cout<<str[1]<<endl;
}
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
task::Init();
task::Solve();
return 0;
}
F - Manju Game
题解
我们把整个序列黑白染色变成
BWBWBWBW的形式
如果是偶数的话
先手可以保证自己得到全部的B或全部的W
后手可以在先手做出选择后,保证自己得到另一种颜色的所有
这样的话,相当于先手得到黑白颜色中较多的那个,后手得到较少的那个
如果是奇数的话
先手还是可以保证自己得到所有B
那么先手选W的话解会不会更优
先手在选B之后,便不可能再选W,如果某一次B进行完了以后先手选了W结果更优,后手可以撤销上一次操作,使得先后手所拿到的物品相反,结果更劣
先手假如可以选\(W_1,W_2,W_3...W_k\)如果,我们能取的区间如果全取B的话,这个区间的B - W是最小的,所以我们限定一下这个区间B - W的最小值,二分一下,然后用一个dp判断即可
代码
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#define enter putchar('\n')
#define space putchar(' ')
#define fi first
#define se second
#define mp make_pair
//#define ivorysi
#define pii pair<int,int>
using namespace std;
typedef long long int64;
template<class T>
void read(T &res) {
res = 0;char c = getchar();T f = 1;
while(c < '0' || c > '9') {
if(c == '-') f = -1;
c = getchar();
}
while(c >= '0' && c <= '9') {
res = res * 10 + c - '0';
c = getchar();
}
res *= f;
}
template<class T>
void out(T x) {
if(x < 0) {putchar('-');x = -x;}
if(x >= 10) out(x / 10);
putchar('0' + x % 10);
}
int N;
int64 a[300005],sum[300005][2];
bool check(int64 mid) {
int64 t = 0;
for(int i = 2 ; i <= N ; i += 2) {
if(sum[i - 1][1] - sum[i - 1][0] + t >= mid) {
t = max(sum[i][0] - sum[i][1],t);
}
}
if(sum[N][1] - sum[N][0] + t >= mid) return true;
return false;
}
void Solve() {
read(N);
for(int i = 1 ; i <= N ; ++i) read(a[i]);
int64 L = 0,R = 0;
for(int i = 1 ; i <= N ; ++i) {
R += a[i];L -= a[i];
sum[i][0] = sum[i - 1][0];
sum[i][1] = sum[i - 1][1];
sum[i][i & 1] += a[i];
}
if(N % 2 == 0) {
out(max(sum[N][0],sum[N][1]));space;out(min(sum[N][0],sum[N][1]));enter;
return;
}
while(L < R) {
int64 mid = (L + R + 1) >> 1;
if(check(mid)) L = mid;
else R = mid - 1;
}
int64 a = L + sum[N][0];
int64 b = sum[N][0] + sum[N][1] - a;
out(a);space;out(b);enter;
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
Solve();
}
【AtCoder】AGC026 题解的更多相关文章
- AtCoder ExaWizards2019题解
AtCoder ExaWizards2019题解 AtCoder (因为代码直接用模板写的,可能有点冗长) A.Regular Triangle 给你三根棍子的长度,问你能否用他们组成等边三角形. 什 ...
- KYOCERA Programming Contest 2021(AtCoder Beginner Contest 200) 题解
KYOCERA Programming Contest 2021(AtCoder Beginner Contest 200) 题解 哦淦我已经菜到被ABC吊打了. A - Century 首先把当前年 ...
- AT2370 Piling Up
https://www.luogu.org/jump/atcoder/2370 题解 答案不是\(2^{2m}\)因为每轮的第一次取球可能会不够. 我们可以设\(dp[i][j]\)表示到了第\(i\ ...
- Triple Shift
来源:Atcoder ARC 136 B - Triple Shift (atcoder.jp) 题解:这道题我们不可能去硬模拟(大多数这种题都不能这样去模拟的),然后我们就要去发现特性, 发现把 a ...
- 重修 Slope Trick(看这篇绝对够!)
Slope Trick 算法存在十余载了,但是我没有找到多少拍手叫好的讲解 blog,所以凭借本人粗拙的理解来写这篇文章. 本文除标明外所有图片均为本人手绘(若丑见谅),画图真的不容易啊 qwq(无耻 ...
- AtCoder Regular Contest 094 (ARC094) CDE题解
原文链接http://www.cnblogs.com/zhouzhendong/p/8735114.html $AtCoder\ Regular\ Contest\ 094(ARC094)\ CDE$ ...
- AtCoder ExaWizards 2019 简要题解
AtCoder ExaWizards 2019 简要题解 Tags:题解 link:https://atcoder.jp/contests/exawizards2019 很水的一场ARC啊,随随便便就 ...
- AtCoder Grand Contest 017 题解
A - Biscuits 题目: 给出 \(n\) 个物品,每个物品有一个权值. 问有多少种选取方式使得物品权值之和 \(\bmod\space 2\) 为 \(p\). \(n \leq 50\) ...
- AtCoder Regular Contest 077 被虐记&题解
直到\(7:58\)才知道今天\(8:00\)有\(AtCoder\)的菜鸡来写题解啦. C - pushpush 题目: 给定一个长为\(n\)的序列,第\(i\)次操作做如下的事 : 将\(a_i ...
随机推荐
- 【刷题】BZOJ 2125 最短路
Description 给一个N个点M条边的连通无向图,满足每条边最多属于一个环,有Q组询问,每次询问两点之间的最短路径. Input 输入的第一行包含三个整数,分别表示N和M和Q 下接M行,每行三个 ...
- 【BZOJ1434】[ZJOI2009]染色游戏(博弈论)
[BZOJ1434][ZJOI2009]染色游戏(博弈论) 题面 BZOJ 洛谷 题解 翻硬币的游戏我似乎原来在博客里面提到过,对于这类问题,当前局面的\(SG\)函数就是所有反面朝上的硬币单一存在时 ...
- JavaScript学习复习
JavaScript 输出 使用 window.alert() 弹出警告框. 使用 document.write() 方法将内容写到 HTML 文档中. 使用 innerHTML 写入到 HTML 元 ...
- 【java】JDK、JRE、JVM的关系
目录结构: contents structure [-] 什么是JDK,JRE,JVM 安装JDK的时候为什么有两个jre 专用JRE 共用JRE 共用JRE和专用JRE的对比 java的跨平台特性 ...
- 【转】如何学习android开发
1.Java基础 很多朋友一上手就开始学习Android,似乎太着急了一些.Android应用程序开发是以Java语言为基础的,所以没有扎实的Java基础知识,只 是机械的照抄别人的代码,是没有任何意 ...
- 使用swagger2配置springboot时出现的问题
这个问题踩了几次坑了,这次又遇到了,不记录一下看来是不长记性了: 测试普通的增删改查的时候,发现删除和查询是对的,可是增加和更新却数据绑定不到controller的参数上面去. 因为是自定义的实体类, ...
- java基础基础总结----- Math(随机数)
前言:math类中感觉最好玩的应该就是随机数 代码: package com.day13.math; import java.util.Random; /** * 类说明 :Math * @autho ...
- properties编程示例
package com.lovo.props; import java.io.FileInputStream;import java.io.FileNotFoundException;import j ...
- 深入了解C指针
前言:复杂类型说明 要了解指针,多多少少会出现一些比较复杂的类型,所以我先介绍一下如何完全理解一个复杂类型,要理解复杂类型其实很简单,一个类型里会出现很多运算符,他们也像普通的表达式一样,有优先级 ...
- vue 使用v-cloak让在页面加载时不显示{{}}花括号
官方说法: 这个指令保持在元素上直到关联实例结束编译. 和 CSS 规则如 [v-cloak] { display: none } 一起用时,这个指令可以隐藏未编译的 Mustache 标签直到实例准 ...