ARC156 解题报告【A~C】
\(\text{By yeminghan}\)
Atcoder Regular Contest 156
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;
}