Educational Codeforces Round 113 (Rated for Div. 2) A-C

Posted 行码棋

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Educational Codeforces Round 113 (Rated for Div. 2) A-C相关的知识,希望对你有一定的参考价值。

A

题意:
找a和b个数相等得一个子区间

思路:
我们找前后相邻两个字母是否是a和b即可

#include<bits/stdc++.h>
using namespace std;
char s[55];
int n;
int main()
{	
	int t;
	cin>>t;
	while(t--)
	{
		cin>>n;
		cin>>s+1;
		int f = 0;
		for(int i=1;i<n;i++)
			if((s[i]=='a')^(s[i+1]=='a'))
			{
				cout<<i<<" "<<i+1<<"\\n";
				f = 1;
				break;
			}
		if(!f) cout<<-1<<" "<<-1<<'\\n';
	}
	return 0;
}

B

题意:
n个玩家,都对应一种结果1(不输)或者2(有胜利的情况)的情况,第i行第j列如果是+,是i战胜了j,若是-,i失败了,若是=,平局,自己打自己为X,求是否存在满足这样的情况

思路:
我们可以将1和2分开来看,如果2的个数小于等于2,肯定不满足。
下面就是满足的情况:
对于所有的1,我们让他们都平局,满足不输的条件。
对于所有的2,我们让每个2对应的玩家打赢前一个位置2对应的玩家,第一个位置的2答应最后一个玩家
最后对没有产生的结果全部设置为平局

#include<bits/stdc++.h>
#define fi first
#define se second
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
typedef vector<int> vi;
typedef vector<ll> vl;
const int dx[]={-1,0,1,0},dy[]={0,1,0,-1};
const int inf = 0x3f3f3f3f;
const ll linf = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-6;
const int mod = 1e9+7;
const int N = 2e5+5,M = 2e5+5;

int n,m,k;
char s[55],g[55][55]; 
int pos[55];

void solve()
{
	memset(g,'\\0',sizeof g);
	cin>>n;
	cin>>s+1;
	int one = 0,two = 0,x = 1;
	for(int i=1;i<=n;i++) 
	{
		if(s[i]=='1') one ++;
		else 
		{
			two ++;
			pos[x++] = i;
		}
	}
	if(two>=1 and two<=2) 
	{
		cout<<"NO\\n";
		return ; 
	}
	int cnt = 1;
	for(int i=1;i<=n;i++)
	{
		if(s[i]=='1')
		{
			for(int j=1;j<=n;j++)
				g[i][j] = '=',g[j][i] = '=';
		}
		else
		{
			if(cnt==1)
			{
				g[i][pos[x-1]]='+',g[pos[x-1]][i]='-';
				cnt++;
			}
			else
			{
				g[i][pos[cnt-1]]='+',g[pos[cnt-1]][i]='-';
				cnt++;
			}
		}
		g[i][i] = 'X';
	}
	cout<<"YES\\n";
	for(int i=1;i<=n;i++,cout<<'\\n')
		for(int j=1;j<=n;j++)
		{
			if(g[i][j]!='=' and g[i][j]!='+' and g[i][j]!='-' and g[i][j]!='X')
				cout<<'=';
			else cout<<g[i][j];
		}
	
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0),cout.tie(0);
	int _;
	cin>>_;
//	_ = 1;
	while(_--)
	{
		solve();
	}
	return 0;
}
 

C

题意:
给定一个序列,从前往后每个数都减一,减到0之后自动跳过,一直进行从前往后的循环,保证相邻两次减一的操作作用于不同的数。求满足这样的条件的排列

思路:
可以发现,最大值与次大值的差大于等于2时,一定不存在这样的序列,结果为0
当最大值的个数大于等于2时,无论怎么排列,两个相等的最大值一直会左右排列的,结果就是全排列的结果 A n n A_n^n Ann

然后就是最大值与次大值的差为1的情况,这时候一定存在一个最大值,次大值的个数不确定,先统计一下次大值的个数 c n t cnt cnt.
必须保证最大值的右边存在一个次大值。 那么这个序列就是满足条件的,可以模拟一下如果最大值在右边会怎么样。

cnt个次大值排列结果为 A c n t c n t A_{cnt}^{cnt} Acntcnt,最大值可以放cnt个位置,总结果为 c n t ∗ A c n t c n t cnt*A_{cnt}^{cnt} cntAcntcnt.
然后再排列剩下的元素,剩下n-cnt-1个元素,一个一个插入:
第一个插入的情况为cnt+2种情况(有cnt+2个位置),下一次就是有cnt+3个位置,以此类推,最后一个有n个位置,结果就是 ( c n t + 2 ) ∗ ( c n t + 3 ) ∗ . . . ∗ n (cnt+2)*(cnt+3)*...*n (cnt+2)(cnt+3)...n

#include<bits/stdc++.h>
#define fi first
#define se second
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
typedef vector<int> vi;
typedef vector<ll> vl;
const int dx[]={-1,0,1,0},dy[]={0,1,0,-1};
const int inf = 0x3f3f3f3f;
const ll linf = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-6;
const int mod = 998244353;
const int N = 2e5+5,M = 2e5+5;

int n,m,k;
ll f[N],a[N];

void solve()
{
	cin>>n;
	for(int i=1;i<=n;i++)
		cin>>a[i];
	sort(a+1,a+1+n,greater<ll>());
	if(a[1]==a[2])
	{
		cout<<f[n]<<'\\n';
		return;
	}
	else if(a[1]-a[2]>=2) 
	{
		cout<<0<<'\\n';
		return;
	}
	else
	{
		int cnt = 1;
		for(int i=3;i<=n;i++)
		{
			if(a[i]==a[2]) cnt++;
			else break;
		}
		ll res = cnt*f[cnt]%mod;
		for(int i=cnt+2;i<=n;i++)
			res = (res*i)%mod;
		cout<<res<<'\\n';
	}
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0),cout.tie(0);
	int _;
	cin>>_;
//	_ = 1;
	f[0] = 1;
	for(int i=1;i<N;i++) 
		f[i] = (f[i-1]*i)%mod;
	while(_--)
	{
		solve();
	}
	return 0;
}
 

以上是关于Educational Codeforces Round 113 (Rated for Div. 2) A-C的主要内容,如果未能解决你的问题,请参考以下文章

Educational Codeforces Round 7 A

Educational Codeforces Round 7

Educational Codeforces Round 90

Educational Codeforces Round 33

Codeforces Educational Codeforces Round 54 题解

Educational Codeforces Round 27