AGC037 A - Dividing a String

洛谷传送门

AGC037A


分析

考虑每一段长度只可能是一或二,设 \(dp[i]\) 表示以 \(i\) 为结尾的前缀最多可以分成多少段。

如果 \(s[i]\) 和 \(s[i-1]\) 不同,那么 \(dp[i]=dp[i-1]+1\),

否则可以将 \(s[i-2,i-1]\) 分成一段,把 \(s[i]\) 分成一段,那么 \(dp[i]=dp[i-3]+2\)

最后的答案就是 \(dp[n]\)


代码

#include <cstdio>
#include <cstring>
using namespace std;
const int N=200011;
int n,dp[N]; char s[N];
int main(){
scanf("%s",s+1),n=strlen(s+1);
for (int i=1;i<=n;++i)
if (s[i]==s[i-1]){
if (i>2) dp[i]=dp[i-3]+2;
else dp[i]=1;
}else dp[i]=dp[i-1]+1;
return !printf("%d",dp[n]);
}

AGC037 B - RGB Balls

洛谷传送门

AGC037B


分析

可以发现只要让第 \(i\) 个人选择每种字母的第 \(i\) 个就能让答案最小。

或者说,只要第三个字母及时匹配就可以让答案最小。

那么维护 \(RG,RB,GB\) 的配对情况,找到一个 \(B,G,R\) 就直接匹配掉。

也就是 \(n!\) 乘上实时可匹配的 \(RG,RB,GB\) 的个数。


代码

#include <cstdio>
using namespace std;
const int N=300011,mod=998244353;
int n,a[N],ans=1,c[11]; char s[N];
int main(){
scanf("%d%s",&n,s+1);
for (int i=1;i<=3*n;++i){
if (s[i]=='R') a[i]=1;
else if (s[i]=='G') a[i]=2;
else a[i]=4;
if (c[7-a[i]]) ans=1ll*ans*(c[7-a[i]]--)%mod;
else if (a[i]!=4&&c[3-a[i]]) ans=1ll*ans*(c[3-a[i]]--)%mod,++c[3];
else if (a[i]!=2&&c[5-a[i]]) ans=1ll*ans*(c[5-a[i]]--)%mod,++c[5];
else if (a[i]!=1&&c[6-a[i]]) ans=1ll*ans*(c[6-a[i]]--)%mod,++c[6];
else ++c[a[i]];
}
for (int i=1;i<=n;++i) ans=1ll*ans*i%mod;
return !printf("%d",ans);
}

AGC037 C - Numbers on a Circle

洛谷传送门

AGC037C


分析

正过来考虑 \(a\) 挺难的,考虑用 \(b\) 倒过来考虑。

当 \(a_i>b_i\) 的时候就是无解,每次找到 \(b\) 未变成 \(a\) 的最大值,

减去 \(b_{i-1}+b_{i+1}\) 就相当于一个操作,这样不断用最大值减就能让答案尽量小。

那么如果 \(\large \frac{b_i-a_i}{b_{i-1}+b_{i+1}}\) 不小于一就可以进行操作,否则一定无解,因为两边的数字也减不了。

可以发现 \(b_i\) 减到不能再减(减去商乘除数)时至少会减半,所以时间复杂度为 \(O(n\log n\log {b_i})\)


代码

#include <cstdio>
#include <cctype>
#include <queue>
using namespace std;
const int N=200011;
int a[N],b[N],n;
long long ans;
int iut(){
int ans=0; char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=ans*10+c-48,c=getchar();
return ans;
}
struct One{
int rk;
bool operator <(const One &t)const{
return b[rk]<b[t.rk];
}
};
priority_queue<One>q;
int main(){
n=iut();
for (int i=1;i<=n;++i) a[i]=iut();
for (int i=1;i<=n;++i){
b[i]=iut();
if (a[i]>b[i]) return !printf("-1");
if (a[i]<b[i]) q.push((One){i});
}
while (!q.empty()){
One t=q.top(); q.pop();
int delta=b[t.rk>1?(t.rk-1):n]+b[t.rk<n?(t.rk+1):1];
if (b[t.rk]-a[t.rk]<delta) return !printf("-1");
int now=(b[t.rk]-a[t.rk])/delta;
ans+=now,b[t.rk]-=now*delta;
if (b[t.rk]>a[t.rk]) q.push(t);
}
return !printf("%lld",ans);
}

AGC037 D - Numbers on a Circle

洛谷传送门

AGC037D


分析

可以发现 \(C\) 只需要满足 \(D\) 的每一行元素与 \(C\) 的每一行元素相同即可。

那么 \(B\) 只需要满足每一列的元素在 \(D\) 中对应的行都互不相同。

把每个元素按照所属的行染色,那么对于每一列跑一次二分图匹配,使得每一行恰好跟一种颜色匹配,

再通过流量判断是哪一行跟哪种颜色匹配,注意这条边不能退流,所以标记之后就不能走了。

时间复杂度 \(O(mn\sqrt{nm})\)


代码

#include <cstdio>
#include <cctype>
#include <algorithm>
#include <queue>
using namespace std;
const int N=211; struct node{int y,w,next;}e[N*N];
int dis[N],v[N*N],n,m,S,T,et=1,as[N],a[N][N],b[N][N];
int iut(){
int ans=0; char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=ans*10+c-48,c=getchar();
return ans;
}
void add(int x,int y,int w){
e[++et]=(node){y,w,as[x]},as[x]=et;
e[++et]=(node){x,0,as[y]},as[y]=et;
}
bool bfs(int S){
for (int i=1;i<=T;++i) dis[i]=0;
queue<int>q; q.push(S),dis[S]=1;
while (!q.empty()){
int x=q.front(); q.pop();
for (int i=as[x];i;i=e[i].next)
if (!v[i]&&e[i].w>0&&!dis[e[i].y]){
dis[e[i].y]=dis[x]+1;
if (e[i].y==T) return 1;
q.push(e[i].y);
}
}
return 0;
}
int min(int a,int b){return a<b?a:b;}
int dfs(int x,int now){
if (x==T||!now) return now;
int rest=0,f;
for (int i=as[x];i;i=e[i].next)
if (!v[i]&&e[i].w>0&&dis[e[i].y]==dis[x]+1){
f=dfs(e[i].y,min(now-rest,e[i].w)),
rest+=f,e[i].w-=f,e[i^1].w+=f;
if (now==rest) return now;
}
if (!rest) dis[x]=0;
return rest;
}
int main(){
n=iut(),m=iut(),S=n<<1|1,T=S+1;
for (int i=1;i<=n;++i) add(S,i,1),add(i+n,T,1);
for (int i=1;i<=n;++i)
for (int j=1;j<=m;++j){
a[j][i]=iut();
add(i,(a[j][i]-1)/m+1+n,1);
}
for (int j=1;j<=m;++j){
for (int i=2;i<=n*4;i+=2) e[i].w=1,e[i^1].w=0;
while (bfs(S)) dfs(S,1e9);
for (int i=1,t=n*4+2;i<=n;++i)
for (int k=1;k<=m;++k,t+=2)
if (!e[t].w&&!v[t]) v[t]=v[t^1]=1,b[j][i]=a[k][i];
}
for (int i=1;i<=n;++i)
for (int j=1;j<=m;++j) printf("%d%c",b[j][i],j==m?10:32);
for (int j=1;j<=m;++j) sort(b[j]+1,b[j]+1+n);
for (int i=1;i<=n;++i)
for (int j=1;j<=m;++j) printf("%d%c",b[j][i],j==m?10:32);
return 0;
}

AT5162 [AGC037E] Reversing and Concatenating

洛谷传送门

AGC037E


分析

找到 \(t\) 所能截取的字典序最小的 \(s\),实际上只需要最后一次截取字典序最小的字符串即可。

或者说就是让最小的字符在开头出现的次数尽量多,并且每进行一次操作,最小的字符在开头出现次数会翻倍(第一次除外)。

那么 \(cnt*2^{k-1}\geq n\) 时实际上答案就是全部都是最小的字符,

否则就是前 \(cnt*2^{k-1}\) 个是最小的,之后的再用字典序最小的字符串补充即可。

可以用二分加哈希判断字典序最小字符串做到 \(O(n\log n)\)


代码

#include <cstdio>
#include <cctype>
using namespace std;
const int N=10011; typedef unsigned long long ull;
char s[N]; ull h[N],p[N]; int n,k,ans,len,mx;
int iut(){
int ans=0; char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=ans*10+c-48,c=getchar();
return ans;
}
ull query(int l,int r){return h[r]-h[l-1]*p[r-l+1];}
bool geq(int X,int Y){
if (query(X,X+n-1)==query(Y,Y+n-1)) return 0;
int l=0,r=n;
while (l<r){
int mid=(l+r+1)>>1;
if (query(X,X+mid-1)!=query(Y,Y+mid-1)) r=mid-1;
else l=mid;
}
return s[X+l]>s[Y+l];
}
int main(){
n=iut(),k=iut(),p[0]=1;
for (int i=1;i<=n;++i){
char ch=getchar();
while (!isalpha(ch)) ch=getchar();
s[i]=s[n*2-i+1]=ch;
}
for (int i=1;i<=n*2;++i) h[i]=h[i-1]*13131+s[i];
for (int i=1;i<=n*2;++i) p[i]=p[i-1]*13131;
ans=n+1;
for (int i=1;i<=n;++i) if (geq(ans,i)) ans=i;
for (int i=0;i<n;++i)
if (s[ans+i]==s[ans]) len=i+1;
else break;
if (k>14||(len<<(k-1))>=n) mx=n;
else mx=len<<(k-1);
for (int i=1;i<=mx;++i) putchar(s[ans]);
for (int i=0;i<n-mx;++i) putchar(s[ans+len+i]);
return 0;
}

AtCoder Grand Contest 037(without F)的更多相关文章

  1. AtCoder Grand Contest 037

    Preface 这篇咕了可能快一个月了吧,正好今天晚上不想做题就来补博客 现在还不去复习初赛我感觉我还是挺刚的(微笑) A - Dividing a String 考虑最好情况把每个字符串当作一个来看 ...

  2. AtCoder Grand Contest 037题解

    传送门 \(A\) 直接把每个字母作为一个字符串,如果某个串和它前面的相同,那么就把这个字母和它后面那个字母接起来.然而我并不会证明这个贪心的正确性 //quming #include<bits ...

  3. AtCoder Grand Contest 037 简要题解

    从这里开始 题目目录 Problem A Dividing a String 猜想每段长度不超过2.然后dp即可. 考虑最后一个长度大于等于3的一段,如果划成$1 + 2$会和后面相同,那么划成$2 ...

  4. Atcoder Grand Contest 026 (AGC026) F - Manju Game 博弈,动态规划

    原文链接www.cnblogs.com/zhouzhendong/AGC026F.html 前言 太久没有发博客了,前来水一发. 题解 不妨设先手是 A,后手是 B.定义 \(i\) 为奇数时,\(a ...

  5. AtCoder Grand Contest 030 (AGC030) F - Permutation and Minimum 动态规划

    原文链接www.cnblogs.com/zhouzhendong/p/AGC030F.html 草率题解 对于每两个相邻位置,把他们拿出来. 如果这两个相邻位置都有确定的值,那么不管他. 然后把所有的 ...

  6. AtCoder Grand Contest 002 (AGC002) F - Leftmost Ball 动态规划 排列组合

    原文链接https://www.cnblogs.com/zhouzhendong/p/AGC002F.html 题目传送门 - AGC002F 题意 给定 $n,k$ ,表示有 $n\times k$ ...

  7. AtCoder Grand Contest 012

    AtCoder Grand Contest 012 A - AtCoder Group Contest 翻译 有\(3n\)个人,每一个人有一个强大值(看我的假翻译),每三个人可以分成一组,一组的强大 ...

  8. AtCoder Grand Contest 011

    AtCoder Grand Contest 011 upd:这篇咕了好久,前面几题是三周以前写的... AtCoder Grand Contest 011 A - Airport Bus 翻译 有\( ...

  9. AtCoder Grand Contest 031 简要题解

    AtCoder Grand Contest 031 Atcoder A - Colorful Subsequence description 求\(s\)中本质不同子序列的个数模\(10^9+7\). ...

  10. AtCoder Grand Contest 010

    AtCoder Grand Contest 010 A - Addition 翻译 黑板上写了\(n\)个正整数,每次会擦去两个奇偶性相同的数,然后把他们的和写会到黑板上,问最终能否只剩下一个数. 题 ...

随机推荐

  1. postgresql中的json和jsonb

    1. 简介postgresql9.3以后,我们可以将表的字段类型设置为json.同时,postgresql还提供了jsonb格式,jsonb是json的二进制形式.二者区别: postgresql9. ...

  2. pymysql基本语法,sql注入攻击,python操作pymysql,数据库导入导出及恢复数据---day38

    1.pymysql基本语法 # ### python操作mysql import pymysql ''' # ### 1.基本语法 #(1) 创建连接 host user password datab ...

  3. 【LeetCode贪心#06】加油站(股票买卖变种)

    加油站 力扣题目链接(opens new window) 在一条环路上有 N 个加油站,其中第 i 个加油站有汽油 gas[i] 升. 你有一辆油箱容量无限的的汽车,从第 i 个加油站开往第 i+1 ...

  4. 【Azure Cloud Service】云服务升级后,查看配置文件发现编码变为utf-16

    问题描述 通过Migrate to ARM,把经典云服务升级成云服务(外延支持)后,在查看云服务的配置XML文件,发现文件的编码格式由 UTF-8 改变为 UTF-16 由此,引发了三个问题 1)Cl ...

  5. 【Azure 应用服务】App Service For Linux 中安装paping, 用于验证从App Service向外请求的网络连通性

    问题描述 App Service For Linux 中安装paping的操作步骤 解决步骤 1) 登录App Service的Kudu站点,点击Bash 2)使用命令下载paping压缩文件:#wg ...

  6. 5、mysql优化--索引使用情况、索引的结构

    避免索引失效 1). 全值匹配 ,对索引中所有列都指定具体值. 2). 最左前缀法则 如果索引了多列,要遵守最左前缀法则.指的是查询从索引的最左前列开始,并且不跳过索引中的列. 3). 范围查询右边的 ...

  7. vscode 函数注释方法 输入 /** 回车 自动就出来了

    vscode 函数注释方法 输入 /** 回车 自动就出来了

  8. 学习笔记-涛讲F#(中级)

    目录 适配器模式 责任链模式 命令模式 策略模式 工厂模式 单例模式 其它内容 这一系列的视频主要讲了F#设计模式的实现,没有太多其它内容,笔记内容主要是转载Snippets tagged desig ...

  9. MFC自定义CStatusBar文字的颜色

    MFC里面的CStatusBar是没法自定义文字颜色的,需要我们自己绘制.这篇文章是在 Display colored text on Status Bar 代码的基础上进行改进的,使用起来更方便. ...

  10. 什么是docker的多阶段构建

    Docker多阶段构建是一种技术,允许在不同的构建阶段中使用不同的基础镜像,并只复制构建所需的文件和依赖项.这种技术旨在减少最终生成的Docker镜像的大小和运行时的资源消耗. 多阶段构建的一般工作流 ...