Educational Codeforces Round 137 (Rated for Div. 2) (A~F)

A. Password(傻逼题)

刚开始看了半年没看懂,后来发现不管前导0的,答案即为6*C(10-n,2)

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



void sol()
{
	scanf("%lld",&n);
	for (ll i=1;i<=n;i++)
		scanf("%lld",&a[i]);
	printf("%lld\n",6*(10-n)*(10-n-1)/2);
	return;
}


int main()
{
	ll tt;
	scanf("%lld",&tt);
	while (tt--)
		sol();
	return 0;
}

B. Permutation Value(思维)

只需构造1,n开头便可以搞出唯一答案

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



void sol()
{
	scanf("%lld",&n);
	printf("1 %lld\n",n);
	for (ll i=2;i<n;i++)
		printf("%lld ",i);
	printf("\n");
	
	return;
}


int main()
{
	ll tt;
	scanf("%lld",&tt);
	while (tt--)
		sol();
	return 0;
}

C. Save the Magazines(贪心/dp)

我们发现对于一个完整的连续1段,假设连续1段为[l,r],则这个完整的连续1段的最大贡献为\sum_{i=l-1}^r a[i] -min(a[l-1],a[l],.....a[r])

并且有每段贡献独立,答案即为最大贡献和

#include <bits/stdc++.h>
#define ll long long
#define ls p<<1
#define rs p<<1|1
#define Ma 1000005
#define mod 1000000007
#define PLL pair<ll,ll>
#define PDD pair<double,double>
using namespace std;
ll n;
ll a[Ma];
string s;


void sol()
{
	scanf("%lld",&n);
	cin>>s;
	for (ll i=1;i<=n;i++)
		scanf("%lld",&a[i]);
	ll ans=0,mi=a[n];
	for (ll i=n;i>=1;i--)
	{
		ans+=a[i];
		if (s[i-1]=='1')
			mi=min(mi,a[i]);
		else
			ans-=min(mi,a[i]),mi=a[i-1];
	}
	printf("%lld\n",ans);
	return;
}


int main()
{
	ll tt;
	scanf("%lld",&tt);
	while (tt--)
		sol();
	return 0;
}

D. Problem with Random Tests(暴力+思维)

首先我们思考一个串

0000111110111000

1.对于该串的前导0部分,我们无法修改,因此该串可以简化为:

111110111000

2.对于更新后的该串前导1部分已经很完美了,我们也不需要进行修改

3.由于串为二进制形式,对于前导1后面的那个0,我们可以把它修改为1,而想要将其修改为1只能用前导1部分

如:s=111110111000,

        t=  11111011100;

但对于后面的1我们无法修改到那个0上(因为小位不能修改大位)

因此就可以理解题目中的随机化拉!

假设出现<=100个前导0后的前缀1,那么复杂度即为O(100n),而错误几率为2^{-101}

#include <bits/stdc++.h>
#define ll long long
#define ls p<<1
#define rs p<<1|1
#define Ma 1000005
#define mod 1000000007
#define PLL pair<ll,ll>
#define PDD pair<double,double>
using namespace std;
ll n;
ll a[Ma];
string s,t;


void sol()
{
	scanf("%lld",&n);
	cin>>s;
	string ma=s;
	ll l=-1;
	for (ll i=0;i<n;i++)
	{
		if (s[i]=='0')
			l++;
		else
			break;
	}
	l++;
	if (l==n)
	{
		printf("0\n");
		return;
	}
	ll f=l;
	for (ll i=l;i<n;i++)
	{
		if (s[i]=='1')
			f=i;
		else
			break;
	}
	f++;
	for (ll i=l;i<f;i++)
	{
		string ans=s;
		ll p=i;
		for (ll j=f;j<n;j++)
		{
			ans[j]=(s[p]-'0')|(ans[j]-'0')+'0';
			p++;
		}
		for (ll j=l;j<n;j++)
		{
			if (ans[j]<ma[j])
				break;
			else if (ans[j]>ma[j])
			{
				ma=ans;
				break;
			}
		}
	}
	for (ll i=l;i<n;i++)
		printf("%c",ma[i]);
	return;
}


int main()
{
		sol();
	return 0;
}

E. FTL(dp)

首先我们规定状态为(w1,w2,g,ti),其中w1为1号充能时间,w2为2号充能时间,g为已经造成的有效伤害,ti为花费的总时间,我们很容易发现其状态有以下三种形式:

(我们默认p1<p2)

(0,0,g,ti),(0,a,g,ti),(b,0,g,ti)

对于所有状态我们会有两种递推情况:

1.->(a,b,g+pi-s,t+T) (a||b)

2.->(0,0,g+p1+p2-s,t+T)

我们可以发现g与ti保证递增有序,那么我们可以将(0,0,g,ti)设置为初始状态,由于相比于ti,g更好成为固定点(因为g<=5000,ti<=5000*1e12)

因此我们枚举g递增,通过1更新答案,2更新初始状态。

复杂度O(n^2)

#include <bits/stdc++.h>
#define ll long long
#define ls p<<1
#define rs p<<1|1
#define Ma 5005
#define mod 1000000007
#define PLL pair<ll,ll>
#define PDD pair<double,double>
using namespace std;
ll a[Ma];
ll ask[Ma];
ll p1,t1,p2,t2,h,s;

void sol()
{
	cin>>p1>>t1>>p2>>t2>>h>>s;
	memset(ask,0x3f,sizeof(ask));
	ask[0]=0;
	ll ans=1e18;
	for (ll ca=0;ca<=h;ca++)
	{
		ll w1=0,w2=0,ti=ask[ca],g=ca;
		while (g<h)
		{
			ll w=max(t1-w1,t2-w2);
			if (g+p1+p2-s>=h)
				ans=min(ans,ti+w);
			else
				ask[g+p1+p2-s]=min(ask[g+p1+p2-s],ti+w);
			w=min(t1-w1,t2-w2);
			ti+=w,w1+=w,w2+=w;
			if (w1==t1)
				w1=0,g+=p1-s;
			if (w2==t2)
				w2=0,g+=p2-s;
			if (g>=h)
				ans=min(ans,ti);
		}
	}
	printf("%lld\n",ans);
	return;
}


int main()
{
		sol();
	return 0;
}

F. Intersection and Union(思维+数据结构)

我们假设前i-1个op操作后,对于集合有数字p出现的贡献为pre1,集合没有有数字p出现的贡献为pre0。我们很容易发现pre0+pre1=3^{i-1}

那么对于第i个op操作

如果S_{i+1}中有数字p,那么pre1将更新为(pre0+pre1)*2[pre0可以用∪,⊕;pre1可以用∩,∪]

如果S_{i+1}中没有数字p,那么pre1将更新为(pre1)*2[pre0无法保留;pre1可以用∩,⊕]

那么对于一个数字p,

F_i=F_{i-1}*2 (p \notin S_{i+1})

F_i=3^{i-1}*2 (p \in S_{i+1})

我们发现只有最后一次在集合S中出现的数字p才是有效的,那么我们就可以用segtree维护区间最大,再单点询问即可。

PS:注意S_1的情况。

复杂度:O(nlogn+2*n)

#include <bits/stdc++.h>
#define ll long long
#define ls p<<1
#define rs p<<1|1
#define Ma 1000005
#define mod 998244353
#define N 300005
#define PLL pair<ll,ll>
#define PDD pair<double,double>
using namespace std;
ll n;
ll a[Ma];
ll po3[Ma],po2[Ma];

struct node
{
	ll l,r,ma,add;
}t[Ma<<2];

void build(ll p,ll l,ll r)
{
	t[p].l=l,t[p].r=r,t[p].ma=t[p].add=0;
	if (l==r)
		return;
	ll mid=(l+r)>>1;
	build(ls,l,mid);
	build(rs,mid+1,r);
	t[p].ma=max(t[ls].ma,t[rs].ma);
	return ;
}

void spread(int p){
	if(t[p].add){
		t[ls].ma=max(t[ls].ma,t[p].add);
		t[rs].ma=max(t[rs].ma,t[p].add);
		t[ls].add=max(t[ls].add,t[p].add);
		t[rs].add=max(t[rs].add,t[p].add);
		t[p].add=0;
	}
	return ;
}

void change(ll p,ll l,ll r,ll d)
{
	if(l<=t[p].l&&r>=t[p].r)
	{
		t[p].ma=max(t[p].ma,d);
		t[p].add=max(t[p].add,d);
		return;
	}
	spread(p);
	ll mid=(t[p].l+t[p].r)>>1;
	if(l<=mid)change(ls,l,r,d);
	if(r>mid)change(rs,l,r,d);
	t[p].ma=max(t[ls].ma,t[rs].ma);
	return ;
}

ll ask(ll p,ll l,ll r)
{
	if(l<=t[p].l&&r>=t[p].r)return t[p].ma;
	spread(p);
	ll mid=(t[p].l+t[p].r)>>1;
	ll val=0;
	if(l<=mid)val=max(val,ask(ls,l,r));
	if(r>mid)val=max(val,ask(rs,l,r));
	return val;
}

void sol()
{
	scanf("%lld",&n);
	po2[0]=po3[0]=1;
	for (ll i=1;i<=N;i++)
		po3[i]=po3[i-1]*3%mod,po2[i]=po2[i-1]*2%mod;
	build(1,0,N);
	for (ll i=1;i<=n;i++)
	{
		ll l,r;
		scanf("%lld%lld",&l,&r);
		change(1,l,r,i);
	}
	ll ans=0;
	for (ll i=0;i<=N;i++)
	{
		ll w=ask(1,i,i);
		if (!w)
			continue;
		else if (w==1)
			ans=(ans+po2[n-1])%mod;
		else
			ans=(ans+po2[n-w+1]*po3[w-2]%mod)%mod;
	}
	printf("%lld\n",ans);
	return;
}


int main()
{
		sol();
	return 0;
}

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
"educational codeforces round 103 (rated for div. 2)"是一个Codeforces平台上的教育性比赛,专为2级选手设计评级。以下是有关该比赛的回答。 "educational codeforces round 103 (rated for div. 2)"是一场Codeforces平台上的教育性比赛。Codeforces是一个为程序员提供竞赛和评级的在线平台。这场比赛是专为2级选手设计的,这意味着它适合那些在算法数据结构方面已经积累了一定经验的选手参与。 与其他Codeforces比赛一样,这场比赛将由多个问题组成,选手需要根据给定的问题描述和测试用例,编写程序来解决这些问题。比赛的时限通常有两到三个小时,选手需要在规定的时间内提交他们的解答。他们的程序将在Codeforces的在线评测系统上运行,并根据程序的正确性和效率进行评分。 该比赛被称为"educational",意味着比赛的目的是教育性的,而不是针对专业的竞争性。这种教育性比赛为选手提供了一个学习和提高他们编程技能的机会。即使选手没有在比赛中获得很高的排名,他们也可以从其他选手的解决方案中学习,并通过参与讨论获得更多的知识。 参加"educational codeforces round 103 (rated for div. 2)"对于2级选手来说是很有意义的。他们可以通过解决难度适中的问题来测试和巩固他们的算法和编程技巧。另外,这种比赛对于提高解决问题能力,锻炼思维和提高团队合作能力也是非常有帮助的。 总的来说,"educational codeforces round 103 (rated for div. 2)"是一场为2级选手设计的教育性比赛,旨在提高他们的编程技能和算法能力。参与这样的比赛可以为选手提供学习和进步的机会,同时也促进了编程社区的交流与合作。
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值