Codeforces Round #517 (Div. 2, based on Technocup 2019 Elimination Round 2)

A:模拟即可

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int M =1e5+7;
int main()
{
	ios::sync_with_stdio(false);cin.tie(0);
	int h,w,k;
	cin>>w>>h>>k;
	int ans=0;
	for(int i=1;i<=k;i++)
	{
		ans+=((h-(i-1)*4-1)*2+(w-(i-1)*4-1)*2);
	}
	cout<<ans<<endl;
	return 0;
}

B:

知道 a|b  和a&b 后 ab的值就确定了。

这是个不错的性质,以后应该能用上,VP时候临时推的。

证明:我们二进制每一位来看。某一位  a&b=1那么 a,b都是1   a&b=0  a|b=0  a,b都是0    ;a&b=0,a|b=1  a,b有一个是1一个是0

所以我们只需要枚举第一个t,然后后面的t都是确定的

模拟下即可。

 

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int M =1e5+7;
int a[M],b[M],c[M];
bool f;
int n;
int main()
{
	ios::sync_with_stdio(false);cin.tie(0);
	cin>>n;
	for(int i=2;i<=n;i++)cin>>a[i];
	for(int i=2;i<=n;i++)cin>>b[i];
	for(int j=0;j<=3;j++)
	{
		for(int i=1;i<=n;i++)c[i]=-1;
		c[1]=j;
		bool f=true;
		for(int i=2;i<=n;i++)
		{
			for(int k=0;k<=3;k++)
			if(((k&c[i-1])==b[i])&&((k|c[i-1])==a[i]))
			c[i]=k;
			if(c[i]==-1)f=false;
		}
//		for(int i=1;i<=n;i++)
//			cout<<c[i]<<" ";
//			cout<<endl;
		if(f)
		{
			cout<<"YES"<<endl;
			for(int i=1;i<=n;i++)
			cout<<c[i]<<" ";
			cout<<endl;
			return 0;
		}
	}
	cout<<"NO"<<endl;
	return 0;
}

C:二分读到第几个笔记。

有两天在学习,其中一天一定可以填满,(从大到小贪心的填)这样另外一天剩的笔记天数是固定的,能就是能,不能就是不能。

满足二分性,二分搞搞即可

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int M =1e5+7;
int p[M],q[M],vs[M];
int sa,sb;
bool ck(int x,int a,int b)//看到第几个笔记 
{
	sa=sb=0;
	memset(vs,0,sizeof(vs));
	for(int i=x;i>=1;i--)
	if(a>=i)a-=i,vs[i]=1;
	ll nw=0;
	for(int i=1;i<=x;i++)
		if(!vs[i])nw+=i;
	if(nw<=b)return true;
	return false;
}
int main()
{
	ios::sync_with_stdio(false);cin.tie(0);
	int a,b;
	cin>>a>>b;
	int l=1,r=1e5+7,ans=0;
	while(l<=r)
	{
		
		int mid=(l+r)/2;
		//cout<<l<<"  "<<r<<"  "<<mid<<endl;
		if(ck(mid,a,b))l=mid+1,ans=mid;
		else r=mid-1;
	}
	//cout<<ans<<endl;
	sa=sb=0;
	memset(vs,0,sizeof(vs));
	for(int i=ans;i>=1;i--)
	if(a>=i)a-=i,p[++sa]=i,vs[i]=1;
	for(int i=1;i<=ans;i++)
		if(!vs[i])q[++sb]=i;
	sort(p+1,p+1+sa);
	cout<<sa<<endl;for(int i=1;i<=sa;i++)cout<<p[i]<<" ";
	cout<<endl;
	cout<<sb<<endl;for(int i=1;i<=sb;i++)cout<<q[i]<<" ";
	cout<<endl;
	return 0;
}

D:

明显的贪心:前面经过的点不是'a' 必然把他换成'a '更优。

所以我们枚举步数,在这一步中选择最优的一个或多个解,然后走下一步。(可以预处理下到i,j.'a'的数量最多的路径是多少)

具体看代码,感觉这种处理比较简单。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int M =2000+7;
char s[M][M];
int f[M][M];//到  x,y的所有路径中, 'a'的个数最多的路径是多少
int vs[M][M]; 
int main()
{
	int n,k;
	cin>>n>>k;
	for(int i=1;i<=n;i++)scanf("%s",s[i]+1);
	for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)f[i][j]=-1e9;
	f[1][1]=(s[1][1]=='a');
	for(int i=1;i<=n;i++)
	for(int j=1;j<=n;j++)
	{
		if(f[i][j]+k>=i+j-1)s[i][j]='a';
		f[i+1][j]=max(f[i][j]+(s[i+1][j]=='a'),f[i+1][j]);
		f[i][j+1]=max(f[i][j]+(s[i][j+1]=='a'),f[i][j+1]);
	}
	vs[1][1]=1;
	for(int step=1;step<=2*n-1;step++)
	{
		char ch='z';
		for(int i=1;i<=n;i++)
		{
			int j=step-i+1;
			if(j<1||j>n||!vs[i][j])continue;
			ch=min(ch,s[i][j]);
		}
		for(int i=1;i<=n;i++)
		{
			int j=step-i+1;
			if(j<1||j>n)continue;
			if(s[i][j]==ch&&vs[i][j])vs[i+1][j]=vs[i][j+1]=1;
		}
		cout<<ch;
	}
	cout<<endl;
	return 0;
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值