Codeforces Round 889 (Div. 2) A-E
传送门,不用谢。
A
给出排列每次可以交换两个数字,求最少多少次使得排列为错排。
考虑在原位的数字个数为\(cnt\)
则答案显然为\((cnt+1)>>1\)
B
求一个最大区间满足其中说有数字被\(n\)整除
极其有趣,注意到样例解释具有迷惑性。
考虑一个序列\([l,r]\)为答案 那么从中可以看出\(1|n,2|n,3|n,...r-l+1|n\)
由此可知\([1,r-l+1]\)也是答案。
那么做法就有了。
C1
给出一个长为\(n\)的序列\(-20\le a_i\le 20\)
每次可以使得\(a_i\)加上\(a_j\),\(i,j\)可以相等。让不超过\(50\)次使得整个序列是不降的。
随便做就行,考虑花\(5\)次培养一个极大值或者极小值。
然后对每个数挨个加譬如用极大值来做给当前\(a_i\)加上两次极大值或者加上一次极大值一次\(a_{i-1}\)。
这样最多\(45\)次。可以通过。
C2
考虑操作被压缩到了\(31\)次。这个界非常的紧。
想了\(1h\)之后发现先将所有数字都变得\(\le 0\)或者\(\ge 0\)再通过一次前缀和或后缀和即可。
前缀和要\(19\)次也就是说通过\(12\)次操作使得整个序列变成上述那样。
考虑正数负数一半一半且正数有最大值,这显然可以完成。
只需要考虑正数比较少且正数有最大值比如正数\(7\)个负数\(13\)个
负数至少是有一个\(-1\)的否则可以认为整个序列已经全部\(\ge 0\)了。
此时利用\(5\)次培养一个极小的负值来让正数全部\(\le 0\)即可。
恰好卡到了\(31\)次。
D
容易想到如果最终结束点是\(i\)那么所得到的价值可以直接知道\((\sum a_i)-(i-1)\)
考虑枚举所有的结束点,问题的关键是当前结束点是否可以到达。
就变成了一个可达性问题,设\(f_{i,j}\)表示用了前\(i\)个数,对于j是否可达。
转移就是普通的背包,这个经典问题可以利用bitset来优化。复杂度\(\frac{n^2}{w}\)
E
这就更有意思了。题意不再赘述。
将问题模型想成数轴上的点,每个点可以往前走。
和前面那个点相遇这个点就消失。
这样由期望的线性性我们假想一个点和前面那个点要么相遇要么不相遇。
每个点如果不和前面点相遇期望步数为\(m+1-a_i\)
那么只需要减去相遇步数即可利用\(f_{x,y}\)表示两点位置的期望要减去步数dp即可。
int n,k,m,T,cnt,lim,B;
int f[MAXN][MAXN];
int ans;
inline int dp(int x,int y)
{
if(x==y)return m-x+1;
if(y==m+1)return 0;
if(f[x][y])return f[x][y];
f[x][y]=((ll)dp(x+1,y)*G+(ll)dp(x,y+1)*G)%mod;
return f[x][y];
}
signed main()
{
freopen("1.in","r",stdin);
sc(n);sc(m);
int x=0,y;
rep(1,n,i)
{
sc(y);
ans=(ans+(m-y+1))%mod;
if(x)ans=(ans+mod-dp(x,y))%mod;
x=y;
}
put(ans);
return 0;
}