AtCoder Grand Contest 030题解
第一次套刷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题解的更多相关文章
- AtCoder Grand Contest 017 题解
A - Biscuits 题目: 给出 \(n\) 个物品,每个物品有一个权值. 问有多少种选取方式使得物品权值之和 \(\bmod\space 2\) 为 \(p\). \(n \leq 50\) ...
- Atcoder Grand Contest 030 F - Permutation and Minimum(DP)
洛谷题面传送门 & Atcoder 题面传送门 12 天以前做的题了,到现在才补/yun 做了一晚上+一早上终于 AC 了,写篇题解纪念一下 首先考虑如果全是 \(-1\) 怎么处理.由于我 ...
- Atcoder Grand Contest 054 题解
那天晚上由于毕业晚会与同学吃饭喝酒没打 AGC,第二天稍微补了下题,目前补到了 E,显然 AGC 的 F 对于我来说都是不可做题就没补了(bushi A 简单题,不难发现如果我们通过三次及以上的操作将 ...
- AtCoder Grand Contest 030 (AGC030) C - Coloring Torus 构造
原文链接https://www.cnblogs.com/zhouzhendong/p/AGC030C.html 题解 才发现当时是被题意杀了. 当时理解的题意是“对于任意的 (i,j) ,颜色 i 和 ...
- AtCoder Grand Contest 031题解
题面 传送门 题解 比赛的之后做完\(AB\)就开始发呆了--简直菜的一笔啊-- \(A - Colorful\ Subsequence\) 如果第\(i\)个字母选,那么它前面任意一个别的字母的选择 ...
- Coloring Torus(Atcoder Grand Contest 030 C)
怎么外国都喜欢考脑筋急转弯…… 题意 输入 $k$,要求构造一个 $n\times n$ 的矩阵($n$ 自选),使得恰好用 $k$ 中颜色把每个点都染色,并且同一种颜色的格子周围 相邻的每种颜色数量 ...
- AtCoder Grand Contest 039 题解
传送门 \(A\) 首先只有一串的情况下,遇到相同的肯定是改后面那一个最优,然后两串的话可能要分奇偶讨论一下 //quming #include<bits/stdc++.h> #defin ...
- 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(& ...
- AtCoder Grand Contest 015题解
传送门 \(A\) 找到能达到的最大的和最小的,那么中间任意一个都可以被表示出来 typedef long long ll; int n,a,b;ll res; int main(){ scanf(& ...
随机推荐
- Storm入门(二)集群环境安装
1.集群规划 storm版本的变更:storm0.9.x storm0.10.x storm1.x上面这些版本里面storm的核心源码是由Java+clojule组成的.storm2.x后期这个 ...
- mybatis insertUseGeneratedKeys 返回主键为null
package tk.mybatis.mapper.common.special; import org.apache.ibatis.annotations.InsertProvider; impor ...
- IdentityServer4实战 - JWT Issuer 详解
一.前言 本文为系列补坑之作,拖了许久决定先把坑填完. 下文演示所用代码采用的 IdentityServer4 版本为 2.3.0,由于时间推移可能以后的版本会有一些改动,请参考查看,文末附上Demo ...
- javascript错误信息
ECMA-262 定义了下列 7 种错误类型: TypeError 类型错误 ReferenceError 引用错误 SyntaxError 语法错误 Error 错误 EvalError 全局错误 ...
- 类Objects
Object类是什么? 在JDK7添加了一个Objects工具类,它提供了一些方法来操作对象,它由一些静态的实用方法组成,这些方法是null-save(空指针安全的)或null-tolerant(容忍 ...
- AtCoder Grand Contest 032-B - Balanced Neighbors (构造)
Time Limit: 2 sec / Memory Limit: 1024 MB Score : 700700 points Problem Statement You are given an i ...
- Django的ORM那些相关操作
一般操作 看专业的官网文档,做专业的程序员! 必知必会13条 <> all(): 查询所有结果 <> filter(**kwargs): 它包含了与所给筛选条件相匹配的对象 & ...
- .netcore2.0发送邮件
SmtpClient smtpClient = new SmtpClient(); smtpClient.DeliveryMethod = SmtpDeliveryMethod.Network;//指 ...
- Linux centos ansible
创建m01.backup.nfs.web01.web02 m01(172.16.1.61).backup(172.16.1.41).nfs(172.16.1.31).web01(172.16.1.7) ...
- 2019-04-18 Beetl模板学习
1. beetl的安装 使用maven: <dependency> <groupId>com.ibeetl</groupId> <artifactId> ...