Loading [MathJax]/jax/output/CommonHTML/jax.js

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上,一开始指向z1。如果p指向的字母等于z1,那么就把z的指针往后移一格,相当于填入了一个字母。然后p继续扫,直到z的指针走到结尾。

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

无解的情况不要忘了。

D

数学题,都是老套路了。

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

翻译一下,就是求

m1x=0[gcd(a,m)=gcd(a+x,m)]

g=gcd(a,m),

原式=m1x=0[gcd(a+x,m)=g]

=a+m1x=a[gcd(x,m)=g]

=a+m1x=1[gcd(x,m)=g]a1x=1[gcd(x,m)=g].

观察xi=1[gcd(i,m)=g]

=xi=1[gcd(ig,mg)=1][g|i] (g|m)显然成立

=xgi=1[gcd(i,mg)=1]

f(x,m)=xi=1[gcd(i,m)=1].

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

F(x,m,g)=xi=1[g|gcd(i,m)]

=[g|m]xi=1[g|i]

f(x,m,g)=xi=1[g=gcd(i,m)]

因此f(x,m,g)=dxgg|dμ(dg)F(x,m,d)

因此f(x,m)=f(x,m,1)=xgd=1μ(d)[d|m]xi=1[d|i]

=dxgd|mμ(d)xd

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

m109,因此质因子最多七八个,肯定能过。

Ans=f(a+m1g,mg)f(a1g,mg).

E

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

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

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

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

k>i,那么原来pk呆在右边,现在它要调换到左边,因此bi要加上ak.

ki,那么原来pk呆在左边,需要被调换到右边,但现在不需要调换了,因此bi要减去ak.

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

1.区间加减一个数;

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

直接上线段树就行。

F

非常牛逼的一道dp。

一个数组,每一位都有一个随机的取值范围,问最后随机出一个不上升的数组的概率。n50,ai1e9.

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

这么考虑:最多2n个端点,把它们全都标到一根数轴上,把线段从左往右分成O(n)段。一个小trick是把原来的每个右端点+1,也就是把区间从[l,r]变成[l,r+1)S1=<l1,r1>,S2=<l2,r2>,...(l1r1l2r2...)

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

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

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

最后一个问题是如何在线段Sj+1=<lj+1,rj+1>=[lj+1,rj+1)上选择k个元素(可重复)?这个是非常经典的组合数学问题,求不定方程x1+x2+...+xn=k的非负整数解的个数。运用挡板法(另一种叫法叫Stars and Bars,都一样),很容易知道这个结果是组合数Cn1k+n1=Ckk+n1.

因此有转移方程f(i+k,j+1)+=f(i,j)Ckk+n1.计算一次转移是O(k)=O(n)的,

因为Ckk+n1=(k+n1)!k!(n1)!=1k!n+k1i=ni.一个状态的前驱状态最多有O(k)=O(n)个,而一共有O(n2n)=O(n2)个状态,所以总复杂度是O(n4)的。事实上在转移时顺带着计算组合数就能变成O(n3)了(吧?)

后记

太棒了,学到许多

posted on   zhugezy  阅读(164)  评论(0编辑  收藏  举报

编辑推荐:
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

导航

统计

点击右上角即可分享
微信分享提示