AGC056 简要题解

A. Three Cells per Row and Column

个人认为 AGC 题的评分普遍都偏低,大概是打 AGC 的人都太强了吧。

每行放 \(3\) 个,我们希望每行都有 \(1\) 的贡献,我们不妨假设第 \(i\) 行恰好贡献在 \(i\) 上。

基于以上的猜测我们有如下构造:

#.##.......
.#.##......
..#.##.....
...#.##....

大概是这样,不过这样右边多出一条,并且最后三行有点问题,调整一下即可。

具体就是在倒数第三行把右边合起来,并在最后两行填好前两列的空缺并造出两个连通块。

比如在 \(6\) 时,构造长这样:

#.##..
.#.##.
..#.##
...###
##....
###..#
点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+10;
const int mod=1e9+7;
#define inf 1e9
inline int read(){
	int x=0,f=1;char c=getchar();
	while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
	while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-'0';c=getchar();}
	return x*f;
}
char C[505][505];
int n,m;
int main(){
	n=read();
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++)C[i][j]='.';
	for(int i=1;i<=n-3;i++)
		C[i][i]=C[i][i+2]=C[i][i+3]='#';
	C[n-2][n-2]=C[n-2][n-1]=C[n-2][n]='#';
	C[n-1][1]=C[n-1][2]=C[n-1][3]='#';
	C[n][1]=C[n][2]=C[n][n]='#';
	for(int i=1;i<=n;i++,puts(""))
		for(int j=1;j<=n;j++)putchar(C[i][j]);
	return 0;
}

B. Range Argmax

你看这个题这个数据范围,一看就是区间 \(dp\),然后枚举最大值划分。但是无限算重,寄。

这个我为啥不会,感觉我应该很会这种的,大概是脑子缺氧了。

我们希望对生成序列相同的当中字典序最小的计数,也就是说,我们对最大值尽量靠前的计数。

也就是说,对于区间 \([l,r]\) 若最大值位于 \(k\),则 \([k+1,r]\) 不重要了,但是 \([l,k-1]\) 中的最大值必须存在一个区间在 \([l,r]\) 且包含它们,否则可以交换。

\(dp_{l,r,k}\) 表示在区间 \([l,r]\) 内且最大值的位置不小于 \(k\) 的方案数,\(S_{l,r,k}\) 表示区间 \([l,r]\) 的最大值位于 \(k\) 时左部最大值最前能摆放的位置。

\(dp_{l,r,k}=dp_{l,r,k+1}+dp_{l,k-1,S_{l,r,k}}dp_{k+1,r,k+1}\)

点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+10;
const int mod=998244353;
#define inf 1e9
inline int read(){
	int x=0,f=1;char c=getchar();
	while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
	while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-'0';c=getchar();}
	return x*f;
}
const int N=505;
int n,m,F[N][N][N],S[N][N][N];
int main(){
	n=read(),m=read();
	memset(S,0x3f,sizeof(S));
	for(int i=1,l,r;i<=m;i++){
		l=read(),r=read();
		for(int j=l;j<=r;j++)
			S[l][r][j]=min(S[l][r][j],l);
	}for(int i=n;i;--i)
		for(int j=i+1;j<=n;j++)
			for(int k=i;k<=j;k++)
				S[i][j][k]=min(S[i][j][k],min(j+1,min(S[i+1][j][k],S[i][j-1][k])));
	for(int i=1;i<=n;i++)F[i][i][i]=1;
	for(int i=1;i<=n+1;i++)
		for(int j=1;j<=n+1;j++)F[i][i-1][j]=1;
	for(int i=n;i;--i)
		for(int j=i+1;j<=n;j++)
			for(int k=j;k>=i;k--)
				F[i][j][k]=(F[i][j][k+1]+1ll*F[i][k-1][S[i][j][k]]*F[k+1][j][k+1])%mod;
	printf("%d\n",F[1][n][1]);
	return 0;
}

C. 01 Balanced

这种题除了逐位确定我想不到别的方法,然后就没有然后了。到目前为止只会 A 题是怎么回事/ll

好吧,我也搞不明白,但反正就是差分约束就是了。期待一个好心哥哥给我讲解捏~

点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+10;
const int mod=1e9+7;
#define inf 1e9
inline int read(){
	int x=0,f=1;char c=getchar();
	while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
	while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-'0';c=getchar();}
	return x*f;
}
int n,m,dis[maxn],vis[maxn];
vector<int>G[maxn];
#define pb push_back
deque<int>Q;
int main(){
	n=read(),m=read();Q.push_front(0);
	for(int i=1;i<=n;i++)dis[i]=inf;
	for(int i=1,l,r;i<=m;i++)
		l=read()-1,r=read(),G[l].pb(r),G[r].pb(l);
	while(!Q.empty()){
		int x=Q.front();Q.pop_front();
		for(auto t:G[x])if(dis[t]>dis[x])
			dis[t]=dis[x],Q.push_front(t);
		if(x&&dis[x-1]>dis[x]+1)
			dis[x-1]=dis[x]+1,Q.push_back(x-1);
		if(x<n&&dis[x+1]>dis[x]+1)
			dis[x+1]=dis[x]+1,Q.push_back(x+1);
	}for(int i=1;i<=n;i++)
		putchar(dis[i]>dis[i-1]?'0':'1');
	return 0;
}
posted @ 2022-12-07 10:56  syzf2222  阅读(81)  评论(0编辑  收藏  举报