ARC156 解题报告【A~C】

\(\text{By yeminghan}\)

Atcoder Regular Contest 156

Contest link

My result

A - Non-Adjacent Flip

1 的个数为 \(k\)

  • 如果 \(k\) 是奇数,显然无解。

  • 如果 \(k\) 为偶数:

    • 如果 \(k\ne2\)\(ans=\dfrac{k}{2}\)读者自证不难。

    • 如果 \(k=2\)

      • 如果两个 1 不相邻,答案为 \(1\)

      • 如果两个 1 相邻,答案大于 \(1\)

        • 如果 \(n\le3\),无解。

        • 如果 \(n=4\)\(S=0110\),答案为 \(3\)

        • 否则答案为 \(2\)

代码思路略有不同。一堆 corner case。

const int N=200005;
int n;string s;
vector<int>a;int ans;
void Solve()
{
	cin>>n>>s;
	a.clear();
	for(int i=1;i<=n;i++)
		if(s[i-1]=='1')a.push_back(i);
	if(a.size()%2)return cout<<-1<<endl,void();
	if(a.size()==2&&a[1]==a[0]+1)
	{
		if(a[0]>2||a[1]+2<=n)cout<<2<<endl;
		else if(a[0]>1&&a[1]+1<=n)cout<<3<<endl;
		else cout<<-1<<endl;
	}
	else cout<<a.size()/2<<endl;
}

B - Mex on Blackboard

可以看出,每次操作可以加一个 \(0\sim\operatorname{mex}\) 之间的数。

如果加的数等于 \(\operatorname{mex}\) 值,那么 \(\operatorname{mex}\) 值就会增大,否则不变。

我们不妨一次不断加 \(\operatorname{mex}\),之后再加其他的数。

这样,问题转换为:给你 \(p\) 次操作,每次可以加一个 \(0\sim q\) 之间的数。求最后生成的可重集的可能个数。

简单打表后发现答案为 \(C_{p+q}^p\)

然后预处理阶乘做完。

const int N=200005;
int n,k,a,p;
bool cx[N<<1];
ModInt jc[N<<1],ans;
ModInt C(int n,int m)
{
	return jc[n]/jc[m]/jc[n-m];
}
void init()
{
	jc[0]=1;
	for(int i=1;i<N<<1;i++)jc[i]=jc[i-1]*ModInt(i);
}
void Solve()
{
	init();
	cin>>n>>k;
	for(int i=1;i<=n;i++){cin>>a;cx[a]=1;}
	p=-1;
	for(int i=0;i<=k;i++)
	{
		for(p++;cx[p];p++);
		ans+=C(p-1+k-i,k-i);
	}
	cout<<ans;
}
posted @ 2023-02-18 21:46  No_Play_Yes_Splay  阅读(87)  评论(0编辑  收藏  举报