Codeforces Round 704

第一次在赛时 \(\text{AK}\) div2 ,有点感动,不过我相信很快就会 \(\text{fst}\) 光的。

Problem A

你就取个模就好了?

代码

#include<bits/stdc++.h>
using namespace std;
#define int long long
void solve(){
	int a,b,c,p;
	cin>>p>>a>>b>>c;
	int res=min((a-p%a)%a,min((b-p%b)%b,(c-p%c)%c));
	printf("%lld\n",res);
}
signed main(){
	int T;cin>>T;
	while(T--) solve();
}

Problem B

你发现只要贪心就好了,让最大的尽量靠上,满足前一个条件之后再使得剩下的中最大的也尽量靠上,然后就好了。

代码

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int n,a[N],b[N];
void solve(){
	cin>>n;
	for(int i=1;i<=n;++i) scanf("%d",&a[i]);
	for(int i=1;i<=n;++i){
		if(a[b[i-1]]>a[i]) b[i]=b[i-1];
		else b[i]=i;
	} 
	int tmp=n;
	while(tmp){
		for(int i=b[tmp];i<=tmp;++i) printf("%d ",a[i]);
		tmp=b[tmp]-1;
	}
	printf("\n");
	return ;
}
int main(){
	int T;cin>>T;
	while(T--) solve();
}

Problem C

这道题你可以处理出第二个串的每一个位置在满足前面(或后面)每一个位置在第一个串中都匹配上的时候,位于第一个串中尽量靠前(或后)的位置是哪里。

这样的话你就可以枚举第二个串的每一个间隔,让前半部分尽可能靠前,后半部分尽可能靠后,然后去一个 \(\max\) 就可以了。可以证明这样不会漏掉答案。

代码

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+5;
int n,m;
char s[N],t[N];
int nxt[N][27];
int L[N],R[N];
int main(){
	cin>>n>>m,scanf("%s%s",s+1,t+1);
	for(int i=1;i<=26;++i) nxt[n+1][i]=n+1;
	for(int i=n;i>=1;--i){
		for(int j=1;j<=26;++j){
			if(j==s[i]-'a'+1) nxt[i][j]=i;
			else nxt[i][j]=nxt[i+1][j];
		}
	}
	int tmp=0;
	for(int i=1;i<=m;++i){
		L[i]=nxt[tmp+1][t[i]-'a'+1];
		tmp=nxt[tmp+1][t[i]-'a'+1];
	}
	for(int i=1;i<=26;++i) nxt[0][i]=0;
	for(int i=1;i<=n;++i){
		for(int j=1;j<=26;++j){
			if(j==s[i]-'a'+1) nxt[i][j]=i;
			else nxt[i][j]=nxt[i-1][j];
		}
	}
	tmp=n+1;
	for(int i=m;i>=1;--i){
		R[i]=nxt[tmp-1][t[i]-'a'+1];
		tmp=nxt[tmp-1][t[i]-'a'+1];
	}
	int res=0;
	for(int i=1;i<m;++i) res=max(res,R[i+1]-L[i]);
	printf("%d\n",res);
	return 0;
}

Problem D

首先因为最高位强制为 \(1\) ,就将 \(b\) 先减去 \(1\)

可以证明,在 \(a>0,b>0\) 的条件下,最大的可能值一定是 \(a+b-2\)

方案的话就是用 \(1\)\(0\)\(b-1\)\(1\) 可以构造出 \(b-1\)\(1\) ,用 \(1\)\(1\)\(a-1\)\(0\) 可以构造出 \(a-1\)\(1\) ,交错排列即可。

然后如果 \(a\)\(b\) 中存在 \(0\) ,最大就只能是 \(0\)

应该就是这样。


发现 \(D\) 果然炸了。

发现我上面的猜测完全错了,实际上非常简单,你只需要保证有一个首尾的 \(0\)\(1\) 互换,然后剩余的部分完全相同,就可以产生互换的区间长度 \(-1\) 的贡献,然后最大值就是 \(a+b-1\) (此处 \(b\) 已减一),特判一下 \(k=0\) 就可以了。

#include<bits/stdc++.h>
using namespace std;
const int N=4e5+5;
int a,b,k;
int x[N],y[N];
int main(){
	cin>>a>>b>>k;
	if(k==0){
		printf("Yes\n");
		for(int i=1;i<=b;++i) printf("1");
		for(int i=1;i<=a;++i) printf("0");
		printf("\n");
		for(int i=1;i<=b;++i) printf("1");
		for(int i=1;i<=a;++i) printf("0");
		printf("\n");
		return 0;
	}
	x[a+b]=y[a+b]=1,b--;
	if(!a||!b||a+b-1<k) return printf("No\n"),0;
	printf("Yes\n");
	for(int i=a+b;i>=a+1;--i) x[i]=y[i]=1;
	for(int i=a;i>=1;--i) x[i]=y[i]=0;
	for(int i=a+b;i>k;--i) if(y[i]&&!y[i-k]){swap(y[i],y[i-k]);break;}
	for(int i=a+b+1;i>=1;--i) printf("%d",x[i]);
	printf("\n");
	for(int i=a+b+1;i>=1;--i) printf("%d",y[i]);
	printf("\n");
	return 0;
}

Prblem E

好题好题。

比较显然的,如果任意两个之间存在不同个数多于 \(4\) ,那么一定不可行。

我们可以将第一个和后面的每一个进行比对,找出差距最大的一个,如果差距最大的小于 \(2\) ,那么直接输出第一个即可,如果差距大于 \(4\) ,那么一定不可行。

那么现在相当于我们只有最多 \(4\) 个位置是不确定的,你直接暴力判断即可。


发现也炸了,我是傻逼。

在差距为 \(3\) 的时候不一定是位于 \(1\) 和差距最大的那个之中,所以说两种暴搜是不一样的。。。

代码

#include<bits/stdc++.h>
using namespace std;
const int N=3e5+5;
int n,m,tmp=1,cnt[N],a[N];
map<int,map<int,int> > mp;
bool tag[N];
void dfs1(int now){
	if(now>m){
		for(int i=1;i<=n;++i){
			int cnt=0;
			for(int j=1;j<=m;++j)
			cnt+=(mp[i][j]!=a[j]);
			if(cnt>2) return ;
		}
		printf("Yes\n");
		for(int j=1;j<=m;++j) printf("%d ",a[j]);
		printf("\n");
		exit(0);
	}
	if(tag[now]) a[now]=mp[1][now],dfs1(now+1);
	else{
		a[now]=mp[1][now],dfs1(now+1);
		a[now]=mp[tmp][now],dfs1(now+1);
	}
}
void dfs2(int now,int cnt1,int cnt2,int cnt3){
	if(now>m){
		if(!cnt1||!cnt2) return ;
		for(int i=1;i<=n;++i){
			int cnt=0;
			for(int j=1;j<=m;++j){
				if(a[cnt3]<0&&j==cnt3) continue;
				cnt+=(mp[i][j]!=a[j]);
			}
			if(a[cnt3]<0&&cnt==2) a[cnt3]=mp[i][cnt3];
			if(cnt>2) return ;
		}
		printf("Yes\n");
		for(int j=1;j<=m;++j){
			if(a[j]==-1) printf("1 ");
			else printf("%d ",a[j]);
		}
		printf("\n");
		exit(0);
	}
	if(tag[now]) a[now]=mp[1][now],dfs2(now+1,cnt1,cnt2,cnt3);
	else{
		if(!cnt1) a[now]=mp[1][now],dfs2(now+1,cnt1+1,cnt2,cnt3);
		if(!cnt2) a[now]=mp[tmp][now],dfs2(now+1,cnt1,cnt2+1,cnt3);
		a[now]=-1,dfs2(now+1,cnt1,cnt2,now);
	}
}
int main(){
	cin>>n>>m;
	for(int i=1;i<=n;++i){
		for(int j=1;j<=m;++j)
		scanf("%d",&mp[i][j]);
	}
	for(int i=2;i<=n;++i){
		for(int j=1;j<=m;++j)
		cnt[i]+=(mp[1][j]!=mp[i][j]);
		if(cnt[i]>4) return printf("No\n"),0;
		if(cnt[i]>cnt[tmp]) tmp=i;
	}
	// printf("%d %d\n",tmp,cnt[tmp]);
	if(cnt[tmp]<=2){
		printf("Yes\n");
		for(int j=1;j<=m;++j) printf("%d ",mp[1][j]);
		return printf("\n"),0;
	}
	for(int j=1;j<=m;++j) tag[j]=(mp[1][j]==mp[tmp][j]);
	if(cnt[tmp]==4) dfs1(1),printf("No\n");
	else dfs2(1,0,0,0),printf("No\n");
	return 0;
}
/*
5 5
1  2  3  4  5 
6  7  3  4  8
1  9  3 10 11
1 12  3  4 15
1  9 14  4 16

1  9  3  4  8
*/
posted @ 2021-02-24 22:20  Point_King  阅读(83)  评论(0编辑  收藏  举报