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} cnt∗Acntcnt.
然后再排列剩下的元素,剩下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