Educational Codeforces Round 120 (Rated for Div. 2)(E已补,F待补)

上次的Codeforces Global Round 18给人整麻了,于是理智的选择了咕咕咕(bushi),看之后的心情更新了。。。。。。

这场总体感觉题目不错,可惜E想歪了,看了T神的E表示人麻了,居然是个暴力+贪心(生无可恋)

PS:中间打的时候还有点小插曲,做完A后看了下C感觉蛮简单的,但写臭了debug了20分钟,心态炸裂,导致B写的慢了。。。

A. Closing The Gap(摸你)

存在两种情况能够满足

1.a+b==c

2.a==b && c%2==0

(写的比较拉)

#include <bits/stdc++.h>
#define ll long long
#define ls p<<1
#define rs p<<1|1
#define Ma 1000005
#define mod 1000000007
using namespace std;
int main()
{
	ll tt;
	scanf("%lld",&tt);
	while (tt--)
	{
		ll a,b,c;
		scanf("%lld%lld%lld",&a,&b,&c);
		if (a==b&&c%2==0)
			printf("YES\n");
		else if (a==c&&b%2==0)
			printf("YES\n");
		else if (b==c&&a%2==0)
			printf("YES\n");
		else if ((a+b+c)==max(max(a,b),c)*2)
			printf("YES\n");
		else
			printf("NO\n");
	}
	return 0;
}

B. Berland Music(贪心)

设cnt0为0的个数,对于0的打分情况为[1,cnt0],对于0来说最小贡献w0为\sum_{1}^{cnt0}(p[i]-i),其中p为升序的0的原得分,同理对于1也成立,因此排序赋值即可。

#include <bits/stdc++.h>
#define ll long long
#define ls p<<1
#define rs p<<1|1
#define Ma 1000005
#define mod 1000000007
using namespace std;

struct node
{
	ll w,num,p,ans;
}t[Ma];

bool cmp1(node x,node y)
{
	return x.w<y.w;
}

bool cmp2(node x,node y)
{
	return x.num<y.num;
}


int main()
{
	ll tt;
	scanf("%lld",&tt);
	while (tt--)
	{
		ll n;
		scanf("%lld",&n);
		for (ll i=0;i<n;i++)
			scanf("%lld",&t[i].w),t[i].num=i;
		string s;
		cin>>s;
		for (ll i=0;i<s.size();i++)
			t[i].p=s[i]-'0';
		sort(t,t+n,cmp1);
		ll add=1;
		for (ll i=0;i<n;i++)
			if (t[i].p==0)
				t[i].ans=add,add++;
		for (ll i=0;i<n;i++)
			if (t[i].p==1)
				t[i].ans=add,add++;
		sort(t,t+n,cmp2);
		for (ll i=0;i<n;i++)
			printf("%lld ",t[i].ans);
		printf("\n");
	}
	return 0;
}

C. Set or Decrease(贪心)

我们发现最优解一定是对数组中的min进行p次操作1(-1),再进行q次操作2(ai=min)

我们可以固定q的次数,求出所需的最小p,那么结果为p+q,只需求出最小的p+q即可

PS:p,q>=0

#include <bits/stdc++.h>
#define ll long long
#define ls p<<1
#define rs p<<1|1
#define Ma 1000005
#define mod 1000000007
using namespace std;
ll a[Ma];

int main()
{
	ll tt;
	scanf("%lld",&tt);
	while (tt--)
	{
		ll n,k;
		scanf("%lld%lld",&n,&k);
		ll sum=0;
		for (ll i=1;i<=n;i++)
			scanf("%lld",&a[i]),sum+=a[i];
		sort(a+1,a+n+1);
		ll ans=sum-k,add=1;//add-1为2的操作次数,ans为p+q
		sum-=a[1];
		for (ll i=n;i>=2;i--)
		{
			add++;
			sum-=a[i];
			ll p;//p代表所需的(a[1]/min)的最大值
			if (k-sum>=0)
				p=(k-sum)/add;
			else
				p=(k-sum-add+1)/add;
			if (p>a[1])
				p=a[1];
			ans=min(ans,(a[1]-p)+add-1);
		}
		if (ans<0)
			ans=0;
		printf("%lld\n",ans);
	}
	return 0;
}

D. Shuffle (数学+排组+容斥)

假设我们可以找出cnt段这样的最优子串,对于第i串为l[i]-r[i],我们运用容斥原理可以得出

ans=(p1+.....+pn)-(p1\capp2+.......)+(p1p2\capp3+...)........

对于p_{a1} \cap p_{a2} \cap p_{a3}....... \cap p_{an}实际=p_{a1} \cap p_{an},其中p_{a1}<p_{a2}<p_{a3}<......<p_{an}

因此ans=(p1+.....+pn)-( p1\capp2+ p2\capp3+ p3\capp4......)

上面内容比较抽象,可以画图理解下。。。。。

#include <bits/stdc++.h>
#define ll long long
#define ls p<<1
#define rs p<<1|1
#define Ma 1000005
#define mod 998244353
using namespace std;
ll l[Ma],r[Ma],tot;
ll a[Ma];
ll mul[Ma],pre[Ma];

ll po(ll p,ll x=mod-2)
{
	ll sum=1;
	while (x)
	{
		if (x&1)
			sum*=p,sum%=mod;
		p*=p,p%=mod;
		x>>=1;
	}
	return sum;
}

void pri()
{
	mul[0]=pre[0]=1;
	for (ll i=1;i<Ma;i++)
		mul[i]=mul[i-1]*i%mod,pre[i]=po(mul[i]);
	return;
}

ll C(ll x,ll y)
{
	if (x<0||y<0||x>y)
		return 0;
	return mul[y]*pre[x]%mod*pre[y-x]%mod;
}

int main()
{
	pri();
	ll n,k;
	scanf("%lld%lld",&n,&k);
	string s;
	cin>>s;
	tot=0;
	for (ll i=0;i<n;i++)
		if (s[i]=='1')
			a[++tot]=i;
	a[0]=-1,a[tot+1]=n;
	if (tot<k||k==0)
		printf("1\n");
	else
	{
		ll ans=0,add=0;
		for (ll i=0;i<=tot-k;i++)
			l[++add]=a[i]+1,r[add]=a[i+k+1]-1;
		for (ll i=1;i<=add;i++)
			ans=(ans+C(k,r[i]-l[i]+1))%mod;
		for (ll i=2;i<=add;i++)
			ans=(ans-C(k-1,r[i-1]-l[i]+1))%mod;
		ans=(ans+mod)%mod;
		printf("%lld\n",ans);
	}
		
	return 0;
}

E. Math Test(贪心+sort)

赛中想的是用神仙(瞎jb乱搞)sort解决,看了T神的code后发现也确实是用神仙sort解决

首先将\sum _{i=1}^{n}|xi-ri|拆开,得出ans=sgni*xi-sgni*ri,其中sgni=(xi>ri)?-1:1,而对于\sumsgni*ri我们可以用贪心将其最大化,而我们只需遍历sgni的符号即可。

复杂度:O(2^{n}(nm+mlogm+m))

PS:确实挺难想的,可能这种类型题目碰见的比较少,赛中真没想到,但并不难

#include <bits/stdc++.h>
#define ll int
#define ls p<<1
#define rs p<<1|1
#define Ma 10005
#define mod 1000000007
using namespace std;
ll a[Ma];
ll n,m;
string s[100];
ll pri[Ma],ma=0;

struct node
{
	ll ans,p[Ma];
	bool operator <(const node &A)const{
		return ans>A.ans;
	}
}t[1<<10];

struct wei
{
	ll num,w;
	bool operator <(const wei &A)const{
		return w>A.w;
	}
}add[Ma];

int main()
{
	ll tt;
	scanf("%d",&tt);
	while (tt--)
	{
		ma=0;
		scanf("%d%d",&n,&m);
		for (ll i=0;i<n;i++)
			scanf("%d",&a[i]);
		for (ll i=0;i<n;i++)
			cin>>s[i];
		for (ll q=0;q<(1<<n);q++)
		{
			t[q].ans=0;
			for (ll i=0;i<m;i++)
				add[i].w=0,add[i].num=i+1;
			for (ll i=0;i<n;i++)
			{	
				ll sgn;
				if (q&(1<<i))
					sgn=1;
				else
					sgn=-1;
				t[q].ans-=sgn*a[i];
				for (ll j=0;j<m;j++)
					if (s[i][j]=='1')
						add[j].w+=sgn;
			}
			sort(add,add+m);
			for (ll j=0;j<m;j++)
			{
				t[q].p[add[j].num]=m-j;
				t[q].ans+=add[j].w*(m-j);
			}
			if (t[q].ans>=ma)
			{
				ma=t[q].ans;
				for (ll i=1;i<=m;i++)
					pri[i]=t[q].p[i];
			}
		}
		for (ll i=1;i<=m;i++)
			printf("%d ",pri[i]);
		printf("\n");
	}
	return 0;
}

  • 7
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值