Codeforces Round 704

第一次在赛时 ( ext{AK}) div2 ,有点感动,不过我相信很快就会 ( ext{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
",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("
");
	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
",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
");
		for(int i=1;i<=b;++i) printf("1");
		for(int i=1;i<=a;++i) printf("0");
		printf("
");
		for(int i=1;i<=b;++i) printf("1");
		for(int i=1;i<=a;++i) printf("0");
		printf("
");
		return 0;
	}
	x[a+b]=y[a+b]=1,b--;
	if(!a||!b||a+b-1<k) return printf("No
"),0;
	printf("Yes
");
	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("
");
	for(int i=a+b+1;i>=1;--i) printf("%d",y[i]);
	printf("
");
	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
");
		for(int j=1;j<=m;++j) printf("%d ",a[j]);
		printf("
");
		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
");
		for(int j=1;j<=m;++j){
			if(a[j]==-1) printf("1 ");
			else printf("%d ",a[j]);
		}
		printf("
");
		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
"),0;
		if(cnt[i]>cnt[tmp]) tmp=i;
	}
	// printf("%d %d
",tmp,cnt[tmp]);
	if(cnt[tmp]<=2){
		printf("Yes
");
		for(int j=1;j<=m;++j) printf("%d ",mp[1][j]);
		return printf("
"),0;
	}
	for(int j=1;j<=m;++j) tag[j]=(mp[1][j]==mp[tmp][j]);
	if(cnt[tmp]==4) dfs1(1),printf("No
");
	else dfs2(1,0,0,0),printf("No
");
	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
*/
原文地址:https://www.cnblogs.com/Point-King/p/14444155.html