Codeforces Round 939 (Div. 2)(A,B,C,D,E1,E2)

news2025/1/16 16:14:07

题目链接

这场不太难,打起来跟 d i v   3 div\ 3 div 3 一样,会者不难。AB找规律,CD构造,E是暴力,带点数学推理。


A. Nene’s Game

题意:

尼尼发明了一种基于整数递增序列 a 1 , a 2 , … , a k a_1, a_2, \ldots, a_k a1,a2,,ak 的新游戏。

在这个游戏中,最初 n n n 个玩家排成一排。在这个游戏的每一轮中,都会发生以下情况:

  • 妮妮找到第 a 1 a_1 a1 、第 a 2 a_2 a2 … \ldots 、第 a k a_k ak 个玩家,他们会同时被踢出游戏。如果一排中的第 i i i 个玩家应该被踢出游戏,但是一排中的玩家少于 i i i 个,那么他们就会被跳过。

一旦在某一轮游戏中没有人被踢出游戏,则宣布所有仍在游戏中的玩家获胜。

例如,假设游戏中有 a = [ 3 , 5 ] a=[3, 5] a=[3,5] 棋手和 n = 5 n=5 n=5 名棋手。让棋手按最初排好的顺序依次命名为棋手 A、棋手 B、 … \ldots 、棋手 E。那么

  • 在第一轮比赛之前,棋手的排列顺序为 ABCDE。妮妮找到了第 3 3 3 个和第 5 5 5 个的棋手。他们在第一轮就被踢出局了。
  • 现在棋手们排成ABD。妮妮发现第 3 3 3 位棋手是棋手D,而且一排中没有第 5 5 5 位棋手。因此,第二轮只有棋手 D 被踢出局。
  • 在第三轮中,没有人被踢出游戏,所以游戏在这一轮后结束。
  • 宣布玩家 A 和 B 获胜。

妮妮还没有决定最初会有多少人参加游戏。妮妮给了你 q q q 个整数 n 1 , n 2 , … , n q n_1, n_2, \ldots, n_q n1,n2,,nq ,你应该针对每个 1 ≤ i ≤ q 1 \le i \le q 1iq 分别回答下面的问题:

  • 如果最初有 n i n_i ni 个玩家参加游戏,有多少人会被宣布为获胜者?

思路:

机翻翻译的一坨。

手玩一下其实就能发现,假设 a a a 数组里最小的数是 a i a_i ai,那么对大于等于 a i a_i ai 的位置的人都迟早会被踢掉。而较小的得以保留,因此最后最多剩余 a i − 1 a_i-1 ai1 个获胜者。

code:

#include <iostream>
#include <cstdio>
using namespace std;
 
int T,n,q;
int minn;
 
int main(){
	cin>>T;
	while(T--){
		cin>>n>>q;
		minn=1e9;
		for(int i=1,t;i<=n;i++){
			cin>>t;
			minn=min(minn,t);
		}
		minn--;
		for(int i=1,t;i<=q;i++){
			cin>>t;
			cout<<min(t,minn)<<" \n"[i==q];
		}
	}
	return 0;
} 

B. Nene and the Card Game

题意:

你和妮妮正在玩纸牌游戏。玩这个游戏使用的是一副有 2 n 2n 2n 张牌的扑克牌。每张牌上都有一个从 1 1 1 n n n 的整数,而 1 1 1 n n n 的每一个整数都正好出现在 2 2 2 张牌上。此外,游戏中还有一张放置纸牌的桌子(最初桌子是空的)。

游戏开始时,这些 2 n 2n 2n 张牌会在你和妮妮之间分配,这样每位玩家都会得到 n n n 张牌。

之后,你和妮妮各 2 n 2n 2n 轮次,即每人轮流 n n n 次,从你开始。每轮

  • 轮到的玩家从手中的牌中选择一张。让 x x x 成为上面的数字。
  • 如果桌面上已经有一张整数为 x x x 的牌,则轮到该玩家的玩家会得到 1 1 1 点数(否则,他不会得到任何点数)。之后,他将选中的带有 x x x 整数的牌放在桌上。

请注意,回合是公开进行的:每个玩家在每个时刻都能看到桌面上的所有牌。

妮妮非常聪明,所以她总是以最佳方式选牌,以便在游戏结束时( 2 n 2n 2n 轮之后)最大化自己的分数。如果她有几种最佳走法,她会选择在游戏结束时使你的得分最小的走法。

更正式地说,妮妮总是以最佳方式轮流下棋,以便在对局结束时首先使她的得分最大化,其次使你在对局结束时的得分最小化。

假设纸牌已经分发完毕,而你手中的纸牌上写有整数 a 1 , a 2 , … , a n a_1, a_2, \ldots, a_n a1,a2,,an ,那么你以最佳方式轮流出牌所能得到的最大分数是多少?

思路:

一个人对手里的一个数字 x x x 的牌,有两种情况:

  1. 有两张,对方一张都没有。
  2. 有一张,对方也有一张。

你如果有两张 x x x,对方因为一张都没有,你打出这张牌对方也做不了什么,在这个数字上拿不到分。如果你只有一张 x x x,因为对方也有一张,对方只要也打出 x x x,对方就可以得分,而你由于没有 x x x 了,就得不到分。

手玩一下,其实很容易发现妮妮出牌的策略。如果你出情况 1 1 1 的两张的牌,那妮妮也出两张的牌。如果你出情况 2 2 2 的一张的牌,那妮妮就跟一张一样的。因为两个人手上的牌型是对称的,你有多少情况 12 12 12 的牌,那么妮妮也有同样数量的牌,妮妮一定是有办法执行上面的出牌策略的。

因此使用这种策略打牌的话,你能得到的最大分数就是情况 1 1 1 的牌的对数。

code:

#include <iostream>
#include <cstdio>
#include <map>
using namespace std;
const int maxn=2e5+5;
 
int T,n;
 
 
int main(){
	cin>>T;
	while(T--){
		cin>>n;
		map<int,int> mp;
		for(int i=1,t;i<=n;i++){
			cin>>t;
			mp[t]++;
		}
		int ans=0;
		for(auto [x,tm]:mp)
			ans+=(tm==2);
		cout<<ans<<endl;
	}
	return 0;
}

C. Nene’s Magical Matrix

题意:

魔法女孩妮妮有一个 n × n n\times n n×n 矩阵 a a a ,矩阵中充满了零。矩阵 a a a i i i 行的第 j j j 个元素表示为 a i , j a_{i, j} ai,j

她可以对这个矩阵进行以下两种类型的运算:

  • 类型 1 1 1 操作:在 1 1 1 n n n 之间选择一个整数 i i i 以及从 1 1 1 n n n 的整数排列 p 1 , p 2 , … , p n p_1, p_2, \ldots, p_n p1,p2,,pn 。同时为所有 1 ≤ j ≤ n 1 \le j \le n 1jn 指定 a i , j : = p j a_{i, j}:=p_j ai,j:=pj
  • 类型 2 2 2 操作:在 1 1 1 n n n 之间选择一个整数 i i i 以及从 1 1 1 n n n 的整数的排列 p 1 , p 2 , … , p n p_1, p_2, \ldots, p_n p1,p2,,pn 。同时为所有 1 ≤ j ≤ n 1 \le j \le n 1jn 指定 a j , i : = p j a_{j, i}:=p_j aj,i:=pj

妮妮想要最大化矩阵 ∑ i = 1 n ∑ j = 1 n a i , j \sum\limits_{i=1}^{n}\sum\limits_{j=1}^{n}a_{i,j} i=1nj=1nai,j 中所有数字的和。她要求你找出使这个和最大化的运算方法。由于她不希望进行过多的运算,你应提供一个运算不超过 2 n 2n 2n 的解决方案。

长度为 n n n 的排列是由 n n n 个不同的整数组成的数组,这些整数从 1 1 1 n n n 按任意顺序排列。例如, [ 2 , 3 , 1 , 5 , 4 ] [2,3,1,5,4] [2,3,1,5,4] 是一个排列,但 [ 1 , 2 , 2 ] [1,2,2] [1,2,2] 不是一个排列( 2 2 2 在数组中出现了两次), [ 1 , 3 , 4 ] [1,3,4] [1,3,4] 也不是一个排列( n = 3 n=3 n=3 但数组中有 4 4 4 )。

思路:

构造题,赛时莫名其妙地一眼出了构造方法,然后一遍过了,然后莫名其妙的三题上蓝。

题面说的很啰嗦,但是实现的操作很简单,就是有一个排列 数组 p p p,然后把 p p p 覆盖到二维数组 a a a 的某一行或列上,操作最多 2 n 2n 2n 次,问二维数组所有元素和最大的构造方法。

直接说构造方法吧,令 p i = i p_i=i pi=i,然后按顺序,用 p p p 数组覆盖第 n n n 行,覆盖第 n n n 列,然后是第 n − 1 n-1 n1 行,第 n − 1 n-1 n1 列,同理一直到第 1 1 1 行,第 1 1 1 列。这样就可以了。构造出来的样子大概如下:

在这里插入图片描述

先只看最大的元素,如果我们只用行操作,我们可以让这个元素摆满一行。同理,用列操作我们可以让这个元素摆满一列。那么 2 n 2n 2n 个操作理论上最多可以让这个最大的元素摆满一行的同时也摆满一列。而次大的元素也是占一行和一列,不过要去掉最大的元素占掉的位置。同理第三大的也占一行和一列,再去掉两个最大的格子和两个次大的格子。而上面的构造方法可以达成这个理论上最多的情况,因此上面的构造方式总和是最大的。

输出方案就很简单了,而元素总和 s u m = ∑ i = 1 n ( 2 ∗ i − 1 ) ∗ i = 2 ∑ i = 1 n i 2 − ∑ i = 1 n i = 2 ∗ n ∗ ( n + 1 ) ∗ ( 2 ∗ n + 1 ) 6 − n ∗ ( n + 1 ) 2 = n ∗ ( n + 1 ) ∗ ( 2 ∗ n + 1 ) 3 − n ∗ ( n + 1 ) 2 sum=\sum_{i=1}^n(2*i-1)*i=2\sum_{i=1}^ni^2-\sum_{i=1}^ni=2*\dfrac{n*(n+1)*(2*n+1)}6-\dfrac{n*(n+1)}2=\dfrac{n*(n+1)*(2*n+1)}3-\dfrac{n*(n+1)}2 sum=i=1n(2i1)i=2i=1ni2i=1ni=26n(n+1)(2n+1)2n(n+1)=3n(n+1)(2n+1)2n(n+1)

code:

#include <iostream>
#include <cstdio>
using namespace std;

int T,n;

int main(){
	cin.tie(0)->sync_with_stdio(false);
	
	cin>>T;
	while(T--){
		cin>>n;
		cout<<n*(n+1)*(2*n+1)/3-n*(n+1)/2<<" "<<2*n<<endl;
		for(int i=n;i>=1;i--){
			cout<<"1 "<<i;
			for(int j=1;j<=n;j++)
				cout<<" "<<j;
			cout<<endl;
			cout<<"2 "<<i;
			for(int j=1;j<=n;j++)
				cout<<" "<<j;
			cout<<endl;
		}
	}
	return 0;
}

D. Nene and the Mex Operator

题意:

妮妮给了你一个长度为 n n n 的整数数组 a 1 , a 2 , … , a n a_1, a_2, \ldots, a_n a1,a2,,an

你可以执行以下操作不超过 5 ⋅ 1 0 5 5\cdot 10^5 5105 次(可能为零):

  • 选择 l l l r r r 这样的两个整数 1 ≤ l ≤ r ≤ n 1 \le l \le r \le n 1lrn ,计算 x x x MEX ⁡ ( { a l , a l + 1 , … , a r } ) \operatorname{MEX}(\{a_l, a_{l+1}, \ldots, a_r\}) MEX({al,al+1,,ar}) ,同时设置 a l : = x , a l + 1 : = x , … , a r : = x a_l:=x, a_{l+1}:=x, \ldots, a_r:=x al:=x,al+1:=x,,ar:=x

这里,整数集合 { c 1 , c 2 , … , c k } \{c_1, c_2, \ldots, c_k\} {c1,c2,,ck} 中的 MEX ⁡ \operatorname{MEX} MEX 被定义为不出现在集合 c c c 中的最小非负整数 m m m

你的目标是最大化数组 a a a 中元素的和。找出最大和,并构建一个操作序列来实现这个和。需要注意的是,你不需要最小化这个序列中的运算次数,你只需要在解决方案中使用不超过 5 ⋅ 1 0 5 5\cdot 10^5 5105 的运算。

思路:

如果序列中的所有数都很小,比如 0 0 0,那么我们肯定用操作给整个序列重新赋值。但是如果有个别位置的值很大,我们 m e x mex mex 值是取不到那么大的,那么这个位置就有可能不操作会更好,而对剩余的两边的序列,又是一个子问题。既然问题本身我们可以找到一个构造方式,那么这个子序列我们也可以找到,也就是可以找到最大值情况,算出来它的值。

显然理论上对一个长为 l e n len len 的序列通过操作可以得到的区间和最大值就是最大的 m e x mex mex 值乘上 l e n len len,也就是 l e n 2 len^2 len2。那么能不能找到一个构造方式来得到它呢?


因为序列原本的值就有可能影响到操作里 m e x mex mex 的结果,所以为了避免这种情况发生,我们先把整个序列置为全 0 0 0。因为 n n n 很小,这里直接暴力枚举来做也未尝不可。假设序列左右端点为 l , r l,r l,r,区间长度为 l e n = r − l + 1 len=r-l+1 len=rl+1,然后手玩一下,发现操作的序列就是: [ l , l ] , [ l , l + 1 ] , [ l , l ] , [ l , l + 2 ] , [ l , l ] , [ l , l + 1 ] , [ l , l ] , [ l , l + 3 ] … [l,l],[l,l+1],[l,l],[l,l+2],[l,l],[l,l+1],[l,l],[l,l+3]\dots [l,l],[l,l+1],[l,l],[l,l+2],[l,l],[l,l+1],[l,l],[l,l+3]分析一下其实就是我们把区间 [ l , r ] [l,r] [l,r] 置为全 l e n len len 需要先构造出区间 [ l , r − 1 ] [l,r-1] [l,r1] 分别为 1 , 2 , 3 , … , l e n − 1 1,2,3,\dots,len-1 1,2,3,,len1 的形式(而构造这个形式就需要先把 [ l , r − 1 ] [l,r-1] [l,r1] 置为全 l e n − 1 len-1 len1,再把 [ l , r − 2 ] [l,r-2] [l,r2] 置为全 l e n − 2 len-2 len2 … \dots ,最后把 [ l , l ] [l,l] [l,l] 置为全 1 1 1),然后再对 [ l , r ] [l,r] [l,r] 用一下操作,这样整个区间就变成了全 l e n len len


这样,我们只要知道了哪些数不参与操作,其他位置通过操作修改为可以修改到的最大值,我们就能算出最后整个区间的值。因为 n = 18 n=18 n=18 很小很小,我们可以直接暴力枚举每种 b a n & p i c k ban\&pick ban&pick 情况,暴力计算每种情况下的序列的值,记录最大的选取情况即可。


而对需要操作的子序列,我们需要模拟上面提出的构造的过程。这个过程很有递归的感觉,所以用递归来实现,具体来说,我们设置一个函数 p p p,参数传入 l , r l,r l,r,表示将区间 [ l , r ] [l,r] [l,r] 替换为全 l e n = r − l + 1 len=r-l+1 len=rl+1

实际实现的时候发现,区间的值是时刻在变化的,如果不同步更新原序列,我们只有第一次检查序列是否全零才是准确的,而在后面操作中,序列我们是知道它每个位置是什么的,因此不需要检查。因此我们还要告诉这个函数:区间是否置为了全 0 0 0,所以再多传入一个参数 i s 0 is0 is0(或者操作时同时暴力地更新序列每个数的改变也是可以的,顶多就是常数大了点)。

code:

#include <iostream>
#include <cstdio>
#include <vector>
#define pii pair<int,int>
using namespace std;
const int maxn=5e5+5;
const int maxk=(1<<18)+5;

int n,a[20];

inline int lowbit(int x){return x&-x;}
inline int sum(int x){return (x==0)?0:x*x;}
int id(int x){
	for(int i=0;;i++)
		if(x>>i&1)
			return i;
}
void pst(int st){
	for(int i=0;i<n;i++)
		cout<<(st>>i&1);
	cout<<endl;
}

int calc(int st){
	int l=0,r,ans=0;
	for(int x=st,lb;x;x^=lb){
		lb=lowbit(x);
		r=id(lb);
		ans+=a[r]+sum(r-l);
		l=r+1;
	}
	ans+=sum(n-l);
	return ans;
}
vector<pii> ans;
void pinit(int l,int r){//区间置为0 
	bool flag=false;
	for(int i=l;i<=r;i++)
		if(a[i]==0){
			flag=true;
			break;
		} 
	ans.push_back(pii(l,r));
	if(flag)ans.push_back(pii(l,r));
}
void p(int l,int r,bool is0){//0~x-1 -> x*x 
	if(!is0)ans.push_back(pii(l,r));//区间置为0 
	if(l==r){
		ans.push_back(pii(l,r));
		return;
	}
	
	for(int i=r-1;i>=l;i--)
		p(l,i,i==r-1);
	ans.push_back(pii(l,r));
}
void print(int st){
	int l=0,r;
	for(int x=st,lb;x;x^=lb){
		lb=lowbit(x);
		r=id(lb);
		
		if(l<r){
			pinit(l,r-1);
			p(l,r-1,true);
		} 
		
		l=r+1;
	}
	if(l<=n-1){
		pinit(l,n-1);
		p(l,n-1,true);
	}
	
	cout<<ans.size()<<endl;
	for(auto [l,r]:ans)
		cout<<l+1<<" "<<r+1<<endl;
}

int main(){
	cin.tie(0)->sync_with_stdio(false);
	
	cin>>n;
	for(int i=0;i<n;i++)cin>>a[i];
	
	int s=0,state;
	for(int st=0;st<(1<<n);st++){
		int t=calc(st);
		if(t>s)s=t,state=st;
	}
	cout<<s<<" ";
	print(state);
	return 0;
}

E1. Nene vs. Monsters (Easy Version)

题意:

这是问题的简单版本。两个版本的唯一区别在于对 a i a_i ai 的限制。只有两个版本的问题都解决了,才能进行破解。

妮妮正在与位于一个圆圈中的 n n n 个怪物战斗。这些怪物的编号从 1 1 1 n n n , 第 i i i 个 ( 1 ≤ i ≤ n 1 \le i \le n 1in )怪物当前的能量值是 a i a_i ai

由于怪物太强大,妮妮决定使用 “攻击你的邻居” 法术与它们战斗。当妮妮使用这个咒语时,以下行动会按以下顺序依次发生:

  • 1 1 1 个怪物攻击第 2 2 2 个怪物;
  • 2 2 2 nd怪物攻击 3 3 3 rd怪物;
  • … \ldots
  • ( n − 1 ) (n-1) (n1) th怪物攻击 n n n th怪物
  • n n n 只怪物攻击第 1 1 1 只怪物

当能量等级为 x x x 的怪物攻击能量等级为 y y y 的怪物时,防守怪物的能量等级变为 max ⁡ ( 0 , y − x ) \max(0, y-x) max(0,yx) (攻击怪物的能量等级仍等于 x x x )。

妮妮会使用这个咒语 1 0 100 10^{100} 10100 次,并处理那些自己的能量值仍然不为零的怪物。她希望你能判断出在她使用所述咒语 1 0 100 10^{100} 10100 次之后,哪些怪物的能量值不会为零。

思路:

这题 2500 2500 2500 分?我觉得 2000 2000 2000 都很水,真的很简单。

手玩一下可以发现整个序列很快就会断成一段一段的(中间有 0 0 0 分隔的)序列。原因就是如果第一个数前面是 0 0 0,这个数每轮都会稳定给后面减去能量值,如果第二个数能坚持住,那么它的能量值应该是比较多的,那么第三个数就惨了,它需要一直承受来自第二个数的摧残,导致它很快就会归零。

算一下第三个数最久能坚持多久。那么我们肯定让第一二个数尽可能的小,假设坚持了 t t t 轮,那么第一个数就是 1 1 1,第二个数就是 t t t,那么第三个数受到的总伤害就是 t − 1 + t − 2 + t − 3 + ⋯ + 0 = t ∗ ( t − 1 ) 2 t-1+t-2+t-3+\dots+0=\dfrac{t*(t-1)}2 t1+t2+t3++0=2t(t1),第三个数的能量是 t 2 t^2 t2 级别的。可以预想到,如果后面还有数的话,数量级应该还会增大,比如第四个数的数量级是 t 3 t^3 t3 级别的等等。

因为序列中的每个数最大也就 2 ∗ 1 0 5 2*10^5 2105,所以第三个数最久也就只能坚持 2 ∗ 1 0 5 \sqrt{2*10^5} 2105 轮左右。我们可以直接暴力地先跑 2 ∗ 1 0 5 \sqrt{2*10^5} 2105 轮,这时剩下的序列最多也就是两个怪挨在一块,这种情况显然第一个怪死不了,而第二个怪一定会死。我们直接统计答案就行了。

code:

#include <iostream>
#include <cstdio>
#include <vector>
using namespace std;
const int maxn=2e5+5;

int T,n,a[maxn];

int main(){
	cin>>T;
	while(T--){
		cin>>n;
		for(int i=0;i<n;i++)cin>>a[i];
		for(int rd=1;rd<=700;rd++){
			for(int i=0;i<n;i++){
				a[(i+1)%n]=max(0,a[(i+1)%n]-a[i]);
			}
		}
//		for(int i=0;i<n;i++)cout<<a[i]<<" \n"[i==n-1];
		for(int i=0;i<n;i++)
			if(a[i]>0 && a[(i+1)%n]>0)
				a[(i+1)%n]=0;
		vector<int> ans;
		for(int i=0;i<n;i++)
			if(a[i]>0)
				ans.push_back(i+1);
		cout<<ans.size()<<endl;
		for(auto x:ans)
			cout<<x<<" ";
		cout<<endl;
	}
	return 0;
}

E2. Nene vs. Monsters (Hard Version)

题意:

这是问题的困难版本。两个版本的唯一区别在于对 a i a_i ai 的限制。只有两个版本的问题都解决了,才能进行破解。

妮妮正在与位于一个圆圈中的 n n n 个怪物战斗。这些怪物的编号从 1 1 1 n n n i i i -th ( 1 ≤ i ≤ n 1 \le i \le n 1in )怪物当前的能量值是 a i a_i ai

由于怪物太强大,妮妮决定使用 "攻击你的邻居 "法术与它们战斗。当妮妮使用这个咒语时,以下行动会按以下顺序逐一发生***:

  • 1 1 1 只怪物攻击第 2 2 2 只怪物;
  • 2 2 2 只怪物攻击第 3 3 3 只怪物;
  • … \ldots
  • ( n − 1 ) (n-1) (n1) 只怪物攻击第 n n n 只怪物
  • n n n 只怪物攻击第 1 1 1 只怪物

当能量等级为 x x x 的怪物攻击能量等级为 y y y 的怪物时,防守怪物的能量等级变为 max ⁡ ( 0 , y − x ) \max(0, y-x) max(0,yx) (攻击怪物的能量等级仍然等于 x x x )。

妮妮会使用这个咒语 1 0 100 10^{100} 10100 次,并对付那些自己的能量值仍然不为零的怪物。她希望你能判断出在她使用所述咒语 1 0 100 10^{100} 10100 次之后,哪些怪物的能量值不会为零。

思路:

有了 E 1 E1 E1 的思路, E 2 E2 E2 的思路也就很好想了,假设循环的轮数是 t t t,那么连续的几个存活的怪物上,第四只怪物需要承受 t 3 t^3 t3 级别的伤害,而怪物血量的上限也就是 1 0 9 10^9 109,因此如果轮数进行了 1 0 9 3 \sqrt[3]{10^9} 3109 级别次,那就不可能出现四只及以上的怪物连续出现的情况。

对剩余的单个怪物,两个怪物连续出现,三个怪物连续出现的情况,我们直接分情况处理一下最终状态就行了。前两个情况很显然,现在讨论第三个情况:

三个怪物连续出现的话,第一个怪一定存活,第二个怪一定死亡,如果第三个怪能坚持到第二个怪死掉,那么它也可以存活。假设第一个怪的能量为 x 1 x_1 x1,第二个怪的能力为 x 2 x_2 x2,第三个怪的能力为 x 3 x_3 x3,设 d = ⌊ x 2 x 1 ⌋ d=\left\lfloor\dfrac{x_2}{x_1}\right\rfloor d=x1x2,这时第三个怪承受的总伤害为 = x 2 − x 1 + x 2 − 2 x 1 + ⋯ + x 2 − d ∗ x 1 = d ∗ x 2 − d ∗ ( d + 1 ) 2 ∗ x 1 =x_2-x_1+x_2-2x_1+\dots+x_2-d*x_1=d*x_2-\dfrac{d*(d+1)}{2}*x_1 =x2x1+x22x1++x2dx1=dx22d(d+1)x1,和 x 3 x_3 x3 比较一下就知道它死不死了。

不过需要注意一点是有可能出现 x n , x 1 , x 2 ≠ 0 x_n,x_1,x_2\not=0 xn,x1,x2=0 的情况,但是我们从第一个数开始枚举,就有可能把它错认为是第二种情况。而且由于攻击顺序不是 x n → x 1 → x 2 x_n\rightarrow x_1\rightarrow x_2 xnx1x2,而是 x 1 → x 2 , x n → x 1 x_1\rightarrow x_2,x_n\rightarrow x_1 x1x2,xnx1,因此第三个怪承受的总伤害变为了 x 2 + x 2 − x 1 + ⋯ + x 2 − d ∗ x 1 = ( d + 1 ) ∗ x 2 − d ∗ ( d + 1 ) 2 ∗ x 1 x_2+x_2-x_1+\dots+x_2-d*x_1=(d+1)*x_2-\dfrac{d*(d+1)}{2}*x_1 x2+x2x1++x2dx1=(d+1)x22d(d+1)x1,需要特判一下。

code:

#include <iostream>
#include <cstdio>
#include <vector>
using namespace std;
typedef long long ll;
const int maxn=2e5+5;

int T,n,a[maxn];

int main(){
	cin.tie(0)->sync_with_stdio(false);
	cin>>T;
	while(T--){
		cin>>n;
		for(int i=0;i<n;i++)cin>>a[i];
		for(int cnt=1,nxt;cnt<=1820;cnt++){//多试几个数,或者直接写个二分算都行
			for(int i=0;i<n;i++){
				nxt=(i+1)%n;
				a[nxt]=max(0,a[nxt]-a[i]);
			}
		}
//		for(int i=0;i<n;i++)cout<<a[i]<<" \n"[i==n-1];
		int st;
		for(st=0;a[st];st++);
		for(int i=0,i1,i2,i3,d;i<n;i++){
			i1=i%n;
			i2=(i+1)%n;
			i3=(i+2)%n;
			if(a[i1]>0 && a[i2]>0 && a[i3]>0){
				d=a[i2]/a[i1];
				ll dt=(2ll*a[i2]-1ll*(d+1)*a[i1])*d/2;
				if(i1>i2)dt+=a[i2];
				a[i3]=max(0ll,(ll)a[i3]-dt);
				
				a[i2]=0;
			}
		}
		for(int i=0,i1,i2,d;i<n;i++){
			i1=i%n;
			i2=(i+1)%n;
			if(a[i1]>0 && a[i2]>0)a[i2]=0;
		}
			
		vector<int> ans;
		for(int i=0;i<n;i++)
			if(a[i]>0)
				ans.push_back(i+1);
		cout<<ans.size()<<"\n";
		for(auto x:ans)
			cout<<x<<" ";
		cout<<"\n";
	}
	return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1608552.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

电大搜题微信公众号:重庆开放大学学子的学习利器

在当今信息化时代&#xff0c;学习已经成为每个人不可或缺的一部分。然而&#xff0c;对于重庆开放大学的学子们来说&#xff0c;由于远程教育的特殊性&#xff0c;他们面临着更大的学习挑战。幸运的是&#xff0c;他们现在可以依靠一款强大的学习利器——电大搜题微信公众号&a…

windows 11 打包python镜像相关操作

第一步&#xff1a;Docker下载 首先先到Docker官网下载最新官方Docker for Windows链接&#xff0c;点击下载之后进行安装&#xff0c;安装好之后在cmd执行 wsl --update。 第二步&#xff1a;在电脑上打开“控制面板”->“程序”-> “启动或关闭Windows功能”。 有的…

简单工厂模式设计实验

实验内容&#xff1a; 楚锋软件公司欲基于Java 语言开发一套图表库&#xff0c;该图表库可以为应用系统提供各种不同外观的图表&#xff0c;例如柱状图、饼状图、折线图等。楚锋软件公司图表库设计人员希望为应用系统开发人员提供一套灵活易用的图表库&#xff0c;而且可以较为…

CalcPad(2) 单位设置和绘制图表

CalcPad(2) 单位设置和绘制图表 Hi uu们&#xff0c;CalcPad用的还好吗&#xff1f;有发现一些问题吗&#xff1f; 在我的使用中&#xff0c;经常需要指定一些计算结果的符号&#xff0c;比如说我希望ADC最小分辨率的计算结果是以uV展示&#xff0c;那我们该怎么操作呢&#…

Aurora 协议学习理解与应用——Aurora 8B10B协议学习

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 Aurora 8B10B协议学习之一&#xff0c;理解协议 概述8B10B数据发送和接收Symbol-Pairs传输调度用户PDU传输过程用户PDU接收过程 流控自然流量控制操作自然流量控制延迟自然流…

【复习笔记】reeRTOS(七) 二值信号量和计数信号量

本文是FreeRTOS复习笔记的第七节&#xff0c;信号量。 上一篇文章&#xff1a; 【复习笔记】FreeRTOS(六) 队列操作 文章目录 一、信号量分类二、二值信号量2.1.实验设计2.2.测试例程2.3.实验效果 三、计数信号量3.1.实验设计3.2.测试例程3.3.实验效果 一、信号量分类 信号量是…

每日算法练习(1)

开一个新坑&#xff0c;记录下自己每天的算法练习&#xff0c;希望自己通过1个多月的学习&#xff0c;能够成为算法大神。 下面正式开始新坑。 两个数组的交集 这是牛客上的题&#xff0c;根据题意&#xff0c;我们有多种解法&#xff0c;这题用哈希比较好写。我们可以弄一个…

(保姆级教学)跨站请求伪造漏洞

1. CSRF漏洞 CSRF&#xff08;Cross-site request forgery&#xff09;跨站请求伪造&#xff0c;也被称为One Click Attack 或者Session Riding&#xff0c;通常缩写为CSRF或者XSRF&#xff0c;是一种对网站的恶意利用。尽管听起来像跨站脚本&#xff08;XSS&#xff09;&…

Linux内核启动过程图解(全程高能)

文章目录 1、进入第一条指令 _text2、start_kernel3、总结(内核启动流程描述) 1、进入第一条指令 _text 编译内核后&#xff0c;打开System.map文件&#xff0c;找到对应的_text和start_kernel ffffff8008080000 T _text //第一条指令 ffffff80096007f4 T start_kernel //…

代码随想录算法训练营第四十四天| 完全背包、518. 零钱兑换 II、377. 组合总和 Ⅳ

一、完全背包 题目链接/文章讲解/视频讲解&#xff1a;https://programmercarl.com/%E8%83%8C%E5%8C%85%E9%97%AE%E9%A2%98%E7%90%86%E8%AE%BA%E5%9F%BA%E7%A1%80%E5%AE%8C%E5%85%A8%E8%83%8C%E5%8C%85.html 状态&#xff1a;已解决 1.问题介绍 完全背包的模板题目&#xff1a;…

dp思维 枚举

题目链接 #include<bits/stdc.h> using namespace std; #define i64 long long const i64 mod 1e9 7; int main() {int n;cin >> n;vector<char>s(n 1);for (int i 1; i < n; i) {cin >> s[i];}//用ans记录所有满足条件的答案数量&#xff0c;c…

linux下使用qt+mpv调用GPU硬件解码

linux下GPU硬件解码接口&#xff0c;常用的有vdpau和vaapi。 mpv是基于mplayer开发的一个播放器。此外&#xff0c;mpv还提供了函数库libmpv&#xff0c;通过使用libmpv可以编写一个简单的播放器。 基于qtlibmpv的demo&#xff0c;官方例子代码如下&#xff1a;https://github.…

STM32之串口中断接收丢失数据

五六年没搞STM32了,这个项目一切都挺顺利,万万没想到被串口接收中断恶心到了。遇到的问题很奇怪 HAL_UART_Receive_IT(&huart1, &rx_buffer[rx_index], LCD_UART_LEN); 这个代码中 LCD_UART_LEN=1的时候,接收过来的数据,数据包的第一个字节总是会跑到rx_buffer的末…

UE5集成gRPC

最近有项目需要在UE5里做RPC&#xff0c;对比了thrift、gRPC、rcplib等开源rpc框架&#xff0c;由于习惯使用protobuf&#xff0c;故选择了gRPC。然而&#xff0c;Google出品也是一言难尽啊&#xff0c;最起码编译太繁琐了。 本次使用的gRPC版本为1.62.1&#xff0c;UE5.2&…

面试stm32基础知识

1.ISP 第一步进入bootloader模式&#xff1a;先置BOOT0为高&#xff0c;BOOT1为低&#xff0c;再复位单片机进入bootloader模式&#xff0c;之后通过上位机下载程序&#xff1b; 第二步配置启动代码的地方&#xff1a;代码下载完毕后&#xff0c;置BOOT0为低&#xff0c;BOOT1…

【NTN 卫星通信】NTN的信关站应该建在哪些地方

1 概述 3GPP的卫星通信讨论了透传星和再生星两种方式。透传星方式&#xff0c;卫星主要是做为中继存在&#xff0c;基本上不做通信协议的处理。再生星方式&#xff0c;gNodeB的主要功能在卫星上&#xff0c;完成通信协议的主要内容。无论是透传星还是再生星&#xff0c;都需要通…

[C++]异常

基本使用 try {int a, b; std::cin >> a >> b;if(b 0) {throw std::runtime_error("unexpected zero");} else {cout << a / b << endl;}} catch(std::exception &e) { cout << "runtime_error: " << e.what() &…

战姬物语部署

一.准备环境 #关闭seliunx和防火墙 setenforce 0 systemctl stop firewalld systemctl disable firewalld #配置源&#xff0c;并安装常用工 curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo curl -o /etc/yum.repos.d/epel.repo …

用队列实现栈(力扣第225题)

#include "stdio.h" #include "stdbool.h" #include "string.h" #include "stdlib.h" #include "assert.h"//初始化队列 typedef int QueueDataType;typedef struct queue {QueueDataType val;struct queue* next; }Qnode;t…

信号处理相关知识

一&#xff1a; 1.序列——三种典型序列通过matlab绘图即可 2.数字信号的自变量一定是整数&#xff0c;幅度上取值是有限的状态&#xff08;不一定是整数&#xff09;。 3.抽取和插值 4.模拟正弦信号sin(wt):w是角频率&#xff0c;单位rad/s,f是频率w/2Π。 5.假设用采样周…