第一次套刷AtCoder

体验良好

传送门


Poisonous Cookies

cout<<b+min(c,a+b+);

Tree Burning

难度跨度有点大啊

可以证明当第一次转向之后,接下来每次的方向都和前一次相反

因为转向后再往相同方向走一定不如初始就往该方向走然后转两次向

枚举初始往哪个方向走以及走几步,前缀和优化即可

#include<ctime>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
#include<vector>
#define rt register int
#define ll long long
using namespace std;
inline ll read(){
ll x=;char zf=;char ch=getchar();
while(ch!='-'&&!isdigit(ch))ch=getchar();
if(ch=='-')zf=-,ch=getchar();
while(isdigit(ch))x=x*+ch-'',ch=getchar();return x*zf;
}
void write(ll y){if(y<)putchar('-'),y=-y;if(y>)write(y/);putchar(y%+);}
void writeln(const ll y){write(y);putchar('\n');}
int k,m,n,x,y,z,cnt,ans;ll ret;
int a[];
ll hz[],qz[],qzh[];
void calc(){
for(rt i=n-;i>=;i--)hz[i]=hz[i+]+2ll*(n-i)*a[i];
qz[]=qzh[]=a[];
for(rt i=;i<=n;i++)qz[i]=qz[i-]+(2ll*i-)*a[i],qzh[i]=qzh[i-]+a[i];
ll ans=;
for(rt i=;i<=n;i++){
ans+=a[i];int md=i+n>>;
ret=max(ret,ans-hz[md+]-(qz[md]-qz[i]-(qzh[md]-qzh[i])*2ll*i)+qzh[n]*(n-i-));
}
}
int main(){
int L=read();n=read();a[++n]=L;
for(rt i=;i<n;i++)a[i]=read();
for(rt i=n;i>=;i--)a[i]-=a[i-];
calc();reverse(a+,a+n+);calc();
cout<<ret;
return ;
}

Coloring Torus

清真构造题

若$ k\leq n$显然可以构一个$ k*k$的正方形,第$ i$行全填$ i$即可

当$ n < k \leq 2n$时,尝试从斜向入手

发现每个斜行可以交错填写数字,这样能填写的数字就能达到$ 2n$级别了

#include<ctime>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
#include<vector>
#define p 1000000007
#define inv2 500000004
#define rt register int
#define ll long long
using namespace std;
inline ll read(){
ll x=;char zf=;char ch=getchar();
while(ch!='-'&&!isdigit(ch))ch=getchar();
if(ch=='-')zf=-,ch=getchar();
while(isdigit(ch))x=x*+ch-'',ch=getchar();return x*zf;
}
void write(ll y){if(y<)putchar('-'),y=-y;if(y>)write(y/);putchar(y%+);}
void writeln(const ll y){write(y);putchar('\n');}
int k,m,n,x,y,z,cnt,ans[][];
int main(){
k=read();
if(k<=){
writeln(k);
for(rt i=;i<=k;i++)for(rt j=;j<=k;j++)cout<<i<<" \n"[j==k];
return ;
}
writeln(n=);
for(rt i=;i<=n;i++){
ans[][i]=i;
for(rt x=n,y=i%n+;x!=;x--,y=y%n+)ans[x][y]=i;
}
for(rt i=n+;i<=k;i++){
if(i+i&)ans[][i]=i;
for(rt x=n,y=i%n+;x!=;x--,y=y%n+)if(i+y&)ans[x][y]=i;
}
for(rt i=;i<=n;i++)for(rt j=;j<=n;j++)cout<<ans[i][j]<<" \n"[j==n];
return ;
}

Inversion Sum

比B和C都清真多了...

设$ f[i][j][k]$表示经过$ i$次操作,$ a_j>a_k$的方案数

容易发现每次操作只对$ O(n)$级别的状态进行了非乘2的修改,其他都只是继承状态然后$ *2$

不妨把状态改成经过$ i$次操作,每次操作有$ 50\%$概率交换两个数,求逆序对的期望

滚动数组之后可以$ O(n^2)$解决转移,最后乘上$ 2^q$即可

#include<ctime>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
#include<vector>
#define p 1000000007
#define inv2 500000004
#define rt register int
#define ll long long
using namespace std;
inline ll read(){
ll x=;char zf=;char ch=getchar();
while(ch!='-'&&!isdigit(ch))ch=getchar();
if(ch=='-')zf=-,ch=getchar();
while(isdigit(ch))x=x*+ch-'',ch=getchar();return x*zf;
}
void write(ll y){if(y<)putchar('-'),y=-y;if(y>)write(y/);putchar(y%+);}
void writeln(const ll y){write(y);putchar('\n');}
int k,m,n,x,y,z,cnt,ans;
int f[][],g[][],a[];
int main(){
n=read();m=read();
for(rt i=;i<=n;i++)a[i]=read();
for(rt i=;i<=n;i++)
for(rt j=;j<=n;j++)if(a[i]>a[j])f[i][j]=;
for(rt i=;i<=m;i++){
x=read();y=read();
for(rt j=;j<=n;j++)g[x][j]=f[x][j],g[j][x]=f[j][x],g[y][j]=f[y][j],g[j][y]=f[j][y];
f[x][y]=f[y][x]=1ll*(g[x][y]+g[y][x])*inv2%p;
for(rt j=;j<=n;j++){
const int v1=1ll*(g[x][j]+g[y][j])*inv2%p,v2=1ll*(g[j][x]+g[j][y])*inv2%p;
if(j!=y&&j!=x)f[x][j]=v1,f[j][x]=v2;
if(j!=x&&j!=y)f[y][j]=v1,f[j][y]=v2;
}
} int ans=;
for(rt i=;i<n;i++)
for(rt j=i+;j<=n;j++)(ans+=f[i][j])%=p;
for(rt i=;i<=m;i++)ans=ans*%p;
cout<<ans;
return ;
}

Less than 3

神仙题!

我们在两个01串中的所有“01”结构之间连一条红线,“10”结构之间连一条蓝线

特判$ n \leq 2$之后发现两个01串等价的充要条件是这两个01串的红蓝线一一对应

发现每次改变非边界的数只会导致一条红/蓝线左移一位或右移一位

改变边界上的数可能会导致生成一条新的红/蓝线或使一条红/蓝线消失不见

容易发现移动不能使同一位置有多条线且线的颜色始终保持红蓝对应

我们可以把边界理解为有无限多条颜色交错的红蓝线

枚举上面的每条红线对应下面的每条红线,红线对答案的贡献就是每组相互对应的线的距离和 蓝线同理

数据范围允许暴力枚举对应$ O(n^2)$通过此题

#include<ctime>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
#include<vector>
#define rt register int
#define ll long long
using namespace std;
inline ll read(){
ll x=;char zf=;char ch=getchar();
while(ch!='-'&&!isdigit(ch))ch=getchar();
if(ch=='-')zf=-,ch=getchar();
while(isdigit(ch))x=x*+ch-'',ch=getchar();return x*zf;
}
void write(ll y){if(y<)putchar('-'),y=-y;if(y>)write(y/);putchar(y%+);}
void writeln(const ll y){write(y);putchar('\n');}
int k,m,n,x,y,z,cnt,ans,ret;
int a[],b[],t1,t2;
char c[],s[];
int calc(){
t1=t2=;
for(rt i=;i<=n;i++)b[++t2]=;
for(rt i=;i<n;i++)if(c[i]==''&&c[i+]=='')a[++t1]=i;
for(rt i=;i<n;i++)if(s[i]==''&&s[i+]=='')b[++t2]=i;
for(rt i=;i<=n;i++)b[++t2]=n;int nowmin=;
for(rt i=;i<=t2-n+;i++){
int ans=;
for(rt j=;j<i;j++)if(b[j])ans+=b[j];
for(rt j=;j<t1;j++)ans+=abs(a[j+]-b[i+j]);
for(rt j=t1;b[i+j]!=n;j++)ans+=n-b[i+j];
nowmin=min(nowmin,ans);
}
return nowmin;
}
int main(){
n=read();
scanf("%s",c+);scanf("%s",s+);
if(n==&&c[]!=s[])writeln();
else if(n==&&c[]!=s[]&&c[]==c[]&&s[]==s[])writeln();
else {
ret=calc();
for(rt i=;i<=n;i++)c[i]=''+''-c[i],s[i]=''+''-s[i];
ret+=calc();cout<<ret;
}
return ;
}

Permutation and Minimum

正推推不出来的DP题启示我们弃疗倒着推

显然两个位置如果都不是$ -1$就可以扔掉

设有cnt组两个位置都是$ -1$则最终答案需要乘上$ cnt!$因为这些组可以任意交换位置

设$ f[i][j][k]$表示已经填了不小于$ i$的所有数,有$ j$个在序列中出现过的数没有被匹配,有$ k$个在原数列中未出现过的数没有被匹配

假设当前数在原序列出现过则可以匹配一个未出现过的数或自己变成一个未被匹配的数

不能匹配一个出现过的数的原因是假设相邻两个数都不是-1则要被扔掉

假设当前数在原序列中未出现过则可以匹配一个未出现过的数,一个出现过的数或自己成为未被匹配的数

注意如果匹配一个出现过的数有$ j$种匹配方式

直接$ O(n^3)DP$即可

#include<ctime>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
#include<vector>
#define p 1000000007
#define rt register int
#define ll long long
using namespace std;
inline ll read(){
ll x=;char zf=;char ch=getchar();
while(ch!='-'&&!isdigit(ch))ch=getchar();
if(ch=='-')zf=-,ch=getchar();
while(isdigit(ch))x=x*+ch-'',ch=getchar();return x*zf;
}
void write(ll y){if(y<)putchar('-'),y=-y;if(y>)write(y/);putchar(y%+);}
void writeln(const ll y){write(y);putchar('\n');}
int k,m,n,x,y,z,cnt,ans;
int a[];bool vis[],nt[];
int q[],t;
int f[][][];
int main(){
n=read();
for(rt i=;i<=*n;i++){
a[i]=read();if(a[i]!=-)vis[a[i]]=;
if(i&^){
if(a[i]==-&&a[i-]==-)cnt++;
if(a[i]!=-&&a[i-]!=-)nt[a[i]]=nt[a[i-]]=;
}
}
for(rt i=;i<=*n;i++)if(!nt[i])if(vis[i])q[++t]=;else q[++t]=;n=t;
//q=1在原数列中
f[n][][]=;
for(rt i=n;i>=;i--){
for(rt j=;j<=n/;j++)
for(rt k=;k<=n/;k++)if(f[i][j][k]){
const int v=f[i][j][k];
if(q[i]){
(f[i-][j+][k]+=v)%=p;
if(k)(f[i-][j][k-]+=v)%=p;
}else {
(f[i-][j][k+]+=v)%=p;
if(k)(f[i-][j][k-]+=v)%=p;
if(j)(f[i-][j-][k]+=1ll*v*j%p)%=p;
}
}
}
int ans=f[][][];
for(rt i=;i<=cnt;i++)ans=1ll*ans*i%p;
cout<<ans;
return ;
}

AtCoder Grand Contest 030题解的更多相关文章

  1. AtCoder Grand Contest 017 题解

    A - Biscuits 题目: 给出 \(n\) 个物品,每个物品有一个权值. 问有多少种选取方式使得物品权值之和 \(\bmod\space 2\) 为 \(p\). \(n \leq 50\) ...

  2. Atcoder Grand Contest 030 F - Permutation and Minimum(DP)

    洛谷题面传送门 & Atcoder 题面传送门 12 天以前做的题了,到现在才补/yun 做了一晚上+一早上终于 AC 了,写篇题解纪念一下 首先考虑如果全是 \(-1\)​ 怎么处理.由于我 ...

  3. Atcoder Grand Contest 054 题解

    那天晚上由于毕业晚会与同学吃饭喝酒没打 AGC,第二天稍微补了下题,目前补到了 E,显然 AGC 的 F 对于我来说都是不可做题就没补了(bushi A 简单题,不难发现如果我们通过三次及以上的操作将 ...

  4. AtCoder Grand Contest 030 (AGC030) C - Coloring Torus 构造

    原文链接https://www.cnblogs.com/zhouzhendong/p/AGC030C.html 题解 才发现当时是被题意杀了. 当时理解的题意是“对于任意的 (i,j) ,颜色 i 和 ...

  5. AtCoder Grand Contest 031题解

    题面 传送门 题解 比赛的之后做完\(AB\)就开始发呆了--简直菜的一笔啊-- \(A - Colorful\ Subsequence\) 如果第\(i\)个字母选,那么它前面任意一个别的字母的选择 ...

  6. Coloring Torus(Atcoder Grand Contest 030 C)

    怎么外国都喜欢考脑筋急转弯…… 题意 输入 $k$,要求构造一个 $n\times n$ 的矩阵($n$ 自选),使得恰好用 $k$ 中颜色把每个点都染色,并且同一种颜色的格子周围 相邻的每种颜色数量 ...

  7. AtCoder Grand Contest 039 题解

    传送门 \(A\) 首先只有一串的情况下,遇到相同的肯定是改后面那一个最优,然后两串的话可能要分奇偶讨论一下 //quming #include<bits/stdc++.h> #defin ...

  8. AtCoder Grand Contest 017题解

    传送门 \(A\) 直接转移就是了 typedef long long ll; const int N=55; ll f[N][2];int a[N],n,p; int main(){ scanf(& ...

  9. AtCoder Grand Contest 015题解

    传送门 \(A\) 找到能达到的最大的和最小的,那么中间任意一个都可以被表示出来 typedef long long ll; int n,a,b;ll res; int main(){ scanf(& ...

随机推荐

  1. pytest生成测试报告-4种方法

    1.生成resultlog文件 2.生成JunitXML文件 3.生成html测试报告 > pip install pytest-html     # 通过pip安装pytest-html 4. ...

  2. Luogu1574 超级数

    Luogu1574 超级数 \(n\) 次询问不超过 \(a_i\) 的最大反素数 \(n\leq10^5,\ a_i\leq10^{17}\) 数论 似乎重题 bzoj1053 [HAOI2007] ...

  3. spring boot(二):启动原理解析

    我们开发任何一个Spring Boot项目,都会用到如下的启动类 @SpringBootApplication public class Application { public static voi ...

  4. javascript错误信息

    ECMA-262 定义了下列 7 种错误类型: TypeError 类型错误 ReferenceError 引用错误 SyntaxError 语法错误 Error 错误 EvalError 全局错误 ...

  5. Python----多项式回归

    多项式线性回归 1.多项式线性方程: 与多元线性回归相比,它只有一个自变量,但有不同次方数. 2.举例: import numpy as np import matplotlib.pyplot as ...

  6. Linux常用命令之Tmux

    Tmux是一个优秀的终端复用软件,类似GNU Screen,但来自于OpenBSD,采用BSD授权.使用它最直观的好处就是,通过一个终端登录远程主机并运行tmux后,在其中可以开启多个控制台而无需再“ ...

  7. springdata 查询思路:基本的单表查询方法(id,sort) ---->较复杂的单表查询(注解方式,原生sql)--->实现继承类---->复杂的多表联合查询 onetomany

    springdata 查询思路:基本的单表查询方法(id,sort) ---->较复杂的单表查询(注解方式,原生sql)--->实现继承类---->复杂的多表联合查询 onetoma ...

  8. iOS presentViewController 方法引起的问题

    有个需求,在项目中随时使用 presentViewController来显示一个界面,比如弹窗提示或者人脸解锁,都是在任何情况都可能出现的. 在presentViewController 调用前,已经 ...

  9. Android技术文章收集

    Android高工必备技能! 我的 Android 开发实战经验总结 Android开发在路上:少去踩坑,多走捷径 //微信 微信Android客户端架构演进之路 微信Android版智能心跳方案 / ...

  10. 聊聊 Scala 的伴生对象及其意义

    2019-04-22 关键字:Scala 伴生对象的作用 关于 Scala 伴生对象,比教材更详细的解释. 什么是伴生对象? 教材中关于伴生对象的解释是:实现类似 Java 中那种既有实例成员又有静态 ...