zhugezy

Educational Codeforces Round 81 (Div. 2) 题解 1295A 1295B 1295C 1295D 1295E 1295F

A

输出111111111...或711111111...即可

B

多一个0,就+1;多一个1,就-1。

记录每一位的前缀和,前面每重复一次字符串s,就相当于整体加几或者减几。因此就是模运算判断一下就好。不能理解的话可以玩一玩这个:101101,然后对x从-5到5都手算一遍看看规律。

C

很经典的贪心题。一个指针\(p\)在s上一直循环前往后扫,另一个指针在z上,一开始指向\(z_1\)。如果\(p\)指向的字母等于\(z_1\),那么就把z的指针往后移一格,相当于填入了一个字母。然后\(p\)继续扫,直到z的指针走到结尾。

当然,这么写肯定会TLE,因此开26张表,每个表存放对应字母的出现位置,维护s的当前指针位置\(p\),接下来需要哪个字母了就去找这个字母的表里大于\(p\)的最小位置,如果不存在就把\(p\)放回起点,ans++。查找大于\(p\)的最小位置可以直接二分,直接调STL里的upper_bound就行。

无解的情况不要忘了。

D

数学题,都是老套路了。

给定\(a,m\),求有多少个\(x\)满足\(0\leq x < m\)\(gcd(a, m)=gcd(a+x,m)\)

翻译一下,就是求

\(\sum\limits_{x=0}^{m-1}[gcd(a,m)=gcd(a+x,m)]\)

\(g=gcd(a,m)\),

原式\(=\sum\limits_{x=0}^{m-1}[gcd(a+x,m)=g]\)

\(=\sum\limits_{x=a}^{a+m-1}[gcd(x,m)=g]\)

\(=\sum\limits_{x=1}^{a+m-1}[gcd(x,m)=g]-\sum\limits_{x=1}^{a-1}[gcd(x,m)=g]\).

观察\(\sum\limits_{i=1}^x[gcd(i,m)=g]\)

\(=\sum\limits_{i=1}^x[gcd(\frac{i}{g},\frac{m}{g})=1][g|i]\) \((g|m)\)显然成立

\(=\sum\limits_{i=1}^{\lfloor\frac{x}{g}\rfloor}[gcd(i,\frac{m}{g})=1]\)

\(f(x,m)=\sum\limits_{i=1}^x[gcd(i,m)=1]\).

容斥的想法很好理解:质因数分解m,二进制状压枚举它的每个质因子选或不选,加加减减就行。下面用反演也能推出一样的结果:

\(F(x,m,g)=\sum\limits_{i=1}^x[g|gcd(i,m)]\)

\(=[g|m]\sum\limits_{i=1}^x[g|i]\)

\(f(x,m,g)=\sum\limits_{i=1}^x[g=gcd(i,m)]\)

因此\(f(x,m,g)=\sum\limits_{g|d}^{d\leq \lfloor\frac{x}{g}\rfloor}\mu(\frac{d}{g})F(x,m,d)\)

因此\(f(x,m)=f(x,m,1)=\sum\limits_{d=1}^{\lfloor\frac{x}{g}\rfloor}\mu(d)[d|m]\sum\limits_{i=1}^x[d|i]\)

\(=\sum\limits_{d|m}^{d\leq \lfloor\frac{x}{g}\rfloor}\mu(d)\lfloor\frac{x}{d}\rfloor\)

这个式子的含义就和上面说的容斥一样。

\(m\leq 10^9\),因此质因子最多七八个,肯定能过。

\(Ans=f(\lfloor\frac{a+m-1}{g}\rfloor, \frac{m}{g})-f(\lfloor\frac{a-1}{g}\rfloor, \frac{m}{g})\).

E

非常巧妙的一道线段树题目。

建立一个数组\(B\)和一个变量\(val\)\(b_i\)表示一开始在第\(i\)个数后面切这一刀,之后调整两边的元素使左边小于等于\(val\),右边大于\(val\)的最小代价。

从小往大枚举\(val\),数组也会随之改变。如果\(val\)\(v\)变成\(v+1\),那么对\(b_i\)进行观察:

\(v+1\)在第\(k\)位(即\(p_k=v+1\)),

\(k>i\),那么原来\(p_k\)呆在右边,现在它要调换到左边,因此\(b_i\)要加上\(a_k\).

\(k \leq i\),那么原来\(p_k\)呆在左边,需要被调换到右边,但现在不需要调换了,因此\(b_i\)要减去\(a_k\).

换句话说,就是这么两个操作:

1.区间加减一个数;

2.查询整个数组的最小值。

直接上线段树就行。

F

非常牛逼的一道dp。

一个数组,每一位都有一个随机的取值范围,问最后随机出一个不上升的数组的概率。\(n\leq 50, a_i\leq 1e9\).

实际上就是统计不下降的数组的个数(把数组倒过来看就行。。。)

这么考虑:最多2n个端点,把它们全都标到一根数轴上,把线段从左往右分成\(O(n)\)段。一个小trick是把原来的每个右端点+1,也就是把区间从\([l,r]\)变成\([l,r+1)\)\(S_1=<l_1,r_1>,S_2=<l_2,r_2>,...(l_1\leq r_1\leq l_2\leq r_2...)\)

\(f(i,j)\)表示数组选择了数组的前\(i\)个元素,且都选择在前\(j\)条线段上的方案数。

假如知道了\(f(i,j)\),那么我们可以枚举一个\(k\),表示在第\(j+1\)条线段上选择数组的接下来\(k\)个元素(\(k\)可以为0)。由于线段互不相交且从左往右排序,无论在这条线段上怎么选择,最后都是一个不上升的数组。

那么就可以从状态\(f(i,j)\)转移到\(f(i+k,j+1)\)

最后一个问题是如何在线段\(S_{j+1}=<l_{j+1},r_{j+1}>=[l_{j+1},r_{j+1})\)上选择\(k\)个元素(可重复)?这个是非常经典的组合数学问题,求不定方程\(x_1+x_2+...+x_n=k\)的非负整数解的个数。运用挡板法(另一种叫法叫Stars and Bars,都一样),很容易知道这个结果是组合数\(C_{k+n-1}^{n-1}=C_{k+n-1}^k\).

因此有转移方程\(f(i+k,j+1)+=f(i,j)*C_{k+n-1}^{k}\).计算一次转移是\(O(k)=O(n)\)的,

因为\(C_{k+n-1}^k=\frac{(k+n-1)!}{k!(n-1)!}=\frac{1}{k!}\prod\limits_{i=n}^{n+k-1}i\).一个状态的前驱状态最多有\(O(k)=O(n)\)个,而一共有\(O(n*2n)=O(n^2)\)个状态,所以总复杂度是\(O(n^4)\)的。事实上在转移时顺带着计算组合数就能变成\(O(n^3)\)了(吧?)

后记

太棒了,学到许多

posted on 2020-02-05 04:20  zhugezy  阅读(159)  评论(0编辑  收藏  举报

导航