首页 > 其他分享 >Codeforces Round #840 (Div. 2) and Enigma 2022 - Cybros LNMIIT(持续更新)

Codeforces Round #840 (Div. 2) and Enigma 2022 - Cybros LNMIIT(持续更新)

时间:2022-12-20 22:56:29浏览次数:40  
标签:CI const 840 int Codeforces Enigma include RI define

Preface

有史以来打的最爆炸的一场,只写了AB

一个原因是最近由于得了新冠导致疏于锻炼,脑子和手都有点不在状态

另一个原因就是没去想C去开一眼感觉很naive的D(事实确实很naive),结果因为下标爆负了死活调不出来

达成七连掉成就,距离八连掉役满只差一场了233


A. Absolute Maximization

只需判断二进制下每一位是否既有\(0\)又有\(1\),是的话答案这一位就是\(1\),否则为\(0\)

#include<cstdio>
#include<iostream>
#define RI register int
#define CI const int&
using namespace std;
const int N=515;
int t,n,a[N],c[10][2];
int main()
{
	//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
	for (scanf("%d",&t);t;--t)
	{
		RI i,j; for (scanf("%d",&n),i=1;i<=n;++i) scanf("%d",&a[i]);
		for (i=0;i<10;++i) c[i][0]=c[i][1]=0;
		for (i=1;i<=n;++i) for (j=0;j<10;++j) ++c[j][(a[i]>>j)&1];
		int ans=0; for (i=0;i<10;++i) if (c[i][0]&&c[i][1]) ans|=(1<<i);
		printf("%d\n",ans);
	}
	return 0;
}

B. Incinerate

话说B题怎么会出细节这么多的模拟来搞心态的,刚开始写挂一个很隐蔽的错误还好后面看出来了

不难发现只要把怪按血量排序后从小到大击杀即可,考虑求出当前杀死剩下的血量最低的怪物所需要的回合数

不难发现这就是一个递减的等差数列求和,求前多少项大于等于某个数的问题,刚开始还在考虑解二次方程的精度问题,后来ztc提醒我直接二分找即可

由于公差是一段后缀的怪物的力量的最小值,可以预处理,总复杂度\(O(n\log n)\)

#include<cstdio>
#include<iostream>
#include<algorithm>
#define RI register int
#define CI const int&
#define int long long
using namespace std;
const int N=100005;
struct data
{
	int hp,atk;
	friend inline bool operator < (const data& A,const data& B)
	{
		return A.hp<B.hp;
	}
}a[N]; int t,n,k,sfx[N];
signed main()
{
	//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
	for (scanf("%lld",&t);t;--t)
	{
		RI i,j; for (scanf("%lld%lld",&n,&k),i=1;i<=n;++i) scanf("%lld",&a[i].hp);
		for (i=1;i<=n;++i) scanf("%lld",&a[i].atk); sort(a+1,a+n+1);
		for (sfx[n]=a[n].atk,i=n-1;i;--i) sfx[i]=min(sfx[i+1],a[i].atk);
		bool flag=1; int sum=0; for (i=1;i<=n&&flag;i=j)
		{
			if (k<=0) flag=0;
			int del=sfx[i],min_hp=a[i].hp-sum,l=1,r=k/del+1,ret=-1;
			while (l<=r)
			{
				int mid=l+r>>1;
				if (mid*k-mid*(mid-1)/2LL*del>=min_hp) ret=mid,r=mid-1; else l=mid+1;
			}
			if (!~ret) flag=0;
			sum+=ret*k-ret*(ret-1)/2LL*del; k-=(ret-1)*del;
			for (j=i;j<=n&&flag;++j) if (a[j].hp>sum) break; k-=sfx[j];
		}
		puts(flag?"YES":"NO");
	}
	return 0;
}

C. Another Array Problem

这个确实是彩笔了没想到结论,直接GG

首先上结论,当\(n>3\)时,答案为\(n\times \max\limits_{1\le i\le n} a_i\),即我们总可以把整个序列都变成某个数

由于连续对区间\([l,r]\)做两次操作就会使得\([l,r]\)全部变成\(0\),然后对一个端点为\(0\),令一个端点为\(x\)的区间操作就可以把这个区间的数变成\(x\)

那么我们设最大值的下标为\(k\),不妨设\(k>2\)(否则镜像操作即可),那么我们可以先把\([1,k-1]\)全部变成\(0\),然后把\([1,k]\)全部变成\(a_k\)

然后再把\([2,n]\)全部变成\(0\),再把\([1,n]\)全部变成\(a_k\)即可

那么只要考虑\(n=2\)和\(n=3\)的特殊情况,分类讨论下即可

#include<cstdio>
#include<iostream>
#include<algorithm>
#define RI register int
#define CI const int&
using namespace std;
const int N=200005;
int t,n,a[N],mx;
int main()
{
	//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
	for (scanf("%d",&t);t;--t)
	{
		RI i; for (scanf("%d",&n),mx=0,i=1;i<=n;++i) scanf("%d",&a[i]),mx=max(mx,a[i]);
		if (n>3) { printf("%lld\n",1LL*n*mx); continue; }
		if (n==2) { printf("%d\n",max(a[1]+a[2],2*abs(a[1]-a[2]))); continue; }
		printf("%lld\n",max(1LL*a[1]+a[2]+a[3],3LL*max(max(a[1],a[3]),max(abs(a[1]-a[2]),abs(a[2]-a[3])))));
	}
	return 0;
}

D. Valid Bitonic Permutations

原来真是个\(O(n)\)题我大呼坑爹,而且由于我刚开始写的时候没有先给\(x,y\)定序导致细节有点多,把下标搞负了直接爆炸

首先不难发现双调序列的峰值一定是\(n\),那么我们不妨枚举\(n\)所在的位置\(p\),此时剩下两种情况(以下默认\(x<y\))

第一种是\(i,j\)在\(p\)的同一侧,由于\(x<y\)所以一定是\(i<j<p\)

我们设\(F(l,r,x)\)表示从数字区间\([l,r]\)里取出\(x\)个数的方案数,即\(F(l,r,x)=C_{r-l+1}^x\)

则这部分的方案数为\(F(1,x-1,i-1)\times F(x+1,y-1,j-i-1)\times F(y+1,n-1,p-j-1)\)

另一种情况就是\(i,j\)在\(p\)的不同侧,即\(i<p<j\)

这部分的定序就需要一点技巧了,我们先选出小于\(x\)的数放在\(i\)左边,即\(F(1,x-1,i-1)\)

然后此时\([1,x-1]\)中剩下的\((x-1)-(i-1)\)个数只能放在\(j\)的右边了,并且一定是按照顺序排好放在右侧的

因此接下来只要在\([x+1,y-1]\)中取\(n-j-((x-1)-(i-1))\)个数放在\(j\)右侧即可,即\(F(x+1,y-1,n-j-((x-1)-(i-1)))\)

最后就是在\([y+1,n]\)中取\(j-p-1\)个数放在\(p\)和\(j\)之间,即\(F(y+1,n,j-p-1)\),而剩下的数只能按顺序放在\(i\)和\(p\)之间了

因此这部分的方案数为\(F(1,x-1,i-1)\times F(x+1,y-1,n-j-((x-1)-(i-1)))\times F(y+1,n,j-p-1)\)

注意当\(x=n\or y=n\)时要特判下,因为\(p\)的位置已经确定了

最后复杂度就是枚举\(n\)的位置,为\(O(n)\)

#include<cstdio>
#include<iostream>
#define RI register int
#define CI const int&
using namespace std;
const int N=105,mod=1e9+7;
int t,n,i,j,x,y,ans,C[N][N];
inline int sum(CI x,CI y)
{
	return x+y>=mod?x+y-mod:x+y;
}
inline void init(CI n)
{
	RI i,j; for (C[0][0]=i=1;i<=n;++i)
	for (C[i][0]=j=1;j<=i;++j) C[i][j]=sum(C[i-1][j],C[i-1][j-1]);
}
inline int F(CI l,CI r,CI t)
{
	if (r-l+1<0||t<0) return 0; return C[r-l+1][t];
}
int main()
{
	//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
	for (init(100),scanf("%d",&t);t;--t)
	{
		scanf("%d%d%d%d%d",&n,&i,&j,&x,&y); ans=0;
		if (x==n)
		{
			if (i==1||i==n) puts("0"); else
			printf("%d\n",1LL*F(y+1,n-1,j-i-1)*F(1,y-1,n-j)%mod);
			continue;
		}
		if (y==n)
		{
			if (j==1||j==n) puts("0"); else
			printf("%d\n",1LL*F(x+1,n-1,j-i-1)*F(1,x-1,i-1)%mod);
			continue;
		}
		for (RI p=2;p<=n-1;++p) if (p!=i&&p!=j)
		{
			if (j<p)
			{
				if (x>y) continue;
				ans=sum(ans,1LL*F(x+1,y-1,j-i-1)*F(1,x-1,i-1)%mod*F(y+1,n-1,p-j-1)%mod);
			} else if (p<i)
			{
				if (x<y) continue;
				ans=sum(ans,1LL*F(y+1,x-1,j-i-1)*F(1,y-1,n-j)%mod*F(x+1,n-1,i-p-1)%mod);
			} else
			{
				if (x<y) ans=sum(ans,1LL*F(1,x-1,i-1)*F(x+1,y-1,n-j-((x-1)-(i-1)))%mod*F(y+1,n-1,j-p-1)%mod);
				else ans=sum(ans,1LL*F(1,y-1,n-j)*F(y+1,x-1,i-1-((y-1)-(n-j)))%mod*F(x+1,n-1,p-i-1)%mod);
			}
		}
		printf("%d\n",ans);
	}
	return 0;
}

标签:CI,const,840,int,Codeforces,Enigma,include,RI,define
From: https://www.cnblogs.com/cjjsb/p/16995286.html

相关文章

  • Codeforces Round #840 (Div. 2) C
    这一道题也是我没想到的题目大意是这样的:可以选择i,j(i<j),我们可以把i到j包括i,j的元素换成abs(a[i],a[j]),并且我们需要的答案就是经过一系列这样的操作,使得这个数组的......
  • Codeforces 1763 F Edge Queries 题解
    题目链接先观察满足题目中给出的限制的图有什么特点。先看\(C_u\),它指的是所有与\(u\)在同一个简单环内的节点。发现一个点v在\(C_u\)中,当且仅当\(u,v\)点双连通。关于点......
  • Codeforces Round #835 (Div. 4) ABCDEF(二分)
    https://codeforces.com/contest/1760【赛时A-E代码】A.MediumNumber题目大意:三个数字,求第二大的数字。input952614342021123111912108206......
  • Codeforces 1774
    A-AddPlusMinusSign简单题,直接\(\tt-\)和\(\tt+\)交替就好了。缺省源没有。intsolve(){ intn=getInt(); strings; cin>>s; boolb=(s[0]==1......
  • Codeforces Round #840 (Div. 2) and Enigma 2022 - Cybros LNMIIT AB
    (:我一开始以为我要爆0了,跌,磕磕绊绊,还好写出了这两题,后面的太难了题目都没看hhhttps://codeforces.com/contest/1763A.AbsoluteMaximization题目大意:给定一个数组a,我......
  • Codeforces Round #839 (Div. 3) ABCD
    昨晚忙着找py数据分析入门了,又......
  • Educational Codeforces Round 140 (Rated for Div. 2)
    A题意:给定二维坐标的三个顶点构成一个三角形。请问能否用一条平行于坐标轴的线段将三角形分割成两个非退化的三角形。核心思路:只有一种情况是无法分割的,那就是是一个直......
  • Codeforces Polynomial Round 2022 (Div.1 + Div.2) CF 1774 题解
    A.AddPlusMinusSign如果有偶数个1,显然可以通过加减各一半的方式达到和为0;否则可以达到和为1。需要注意如果序列的第一个数是1,则它的前面只能填加号。时间复杂度\(O(n......
  • Codeforces Polynomial Round 2022 (Div.1 + Div.2) CF 1774 题解
    A.AddPlusMinusSign如果有偶数个1,显然可以通过加减各一半的方式达到和为0;否则可以达到和为1。需要注意如果序列的第一个数是1,则它的前面只能填加号。时间复杂度\(O(n......
  • Codeforces Polynomial Round 2022 (Div.1 + Div.2) CF 1774 题解
    A.AddPlusMinusSign如果有偶数个1,显然可以通过加减各一半的方式达到和为0;否则可以达到和为1。需要注意如果序列的第一个数是1,则它的前面只能填加号。时间复杂度\(O(n......