POJ3379 增环路径展开(标题是我瞎起的)

博客探讨了POJ3379算法问题,涉及一个反向约瑟夫环的解题方法。通过将不断变化的环展开为路径,利用路径长度和节点增量来计算操作后的节点值。博主详细解释了如何将环转化为路径,以及如何反向操作,最终得出答案。讨论了处理复杂度并指出将难以分析的环结构转化为路径的思路是解决问题的关键。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

poj.org/problem?id=3379

很好的一道考察智商/灵性的题,对于我这种老年选手难度挺大的,想了大半天才捋清思路

大概题意是

一个长度n的环,从第1的位置开始,每次往后数k个位置,并在第k个位置之后插入一个新的节点,新点的值为第k个位置点的值+1,然后以这个新节点开始重复,求操作m次后最后插入的节点的值

貌似是个反向的约瑟夫环,也确实是个反向约瑟夫环,但是如何反向操作呢?

环的结构,尤其是变化的环,很不友好,(就像绝对值函数一样,非线性不好处理,可以想办法转回为线性)

这里的思路是,把不断变化的环,展开成路径,每经过一个节点,或是插入一个新节点,相当于在前进路径上增加了一个节点, 用(i,d)表示路径上的节点,i表示初始环的索引,d表示当前节点的值与初始环上索引为i的点的值之间的增量,那么

1. 进行1此操作后,路径长度是1+(k+1), 操作m次后,路径长度是1+(k+1)*m, 所以一个长度为L的路径, 最多的操作数是(L-1)/(k+1) (路径长度可以是任意,所以最末位的点不一定是新增的点)

2. 一个长度为L的路径对应的环的长度为s=n+(L-1)/(k+1), 所以如果L>s则路径中的最后s个点就代表当前的环,把这s个点驱除后路径长度变为 L-s, 并且路径末尾点(i, d)中i保持不便,如果路径为L的末尾的点恰好是新增点,那么d-1,否则d也不变, 而只有当L=1+(k+1)*x (x>0)的时候,路径末尾点才会是新增点; 记录d发生变化的次数dd

这样不断进行反向操作,最后的路径就变成了满足L-(L-1)/(k+1) <= n的路径,这个路径的末尾节点(i, d) = L-(L-1)/(k+1)-1, L>1&&((L-1)%(k+1))==0, 最终的答案就是(i, d+dd)

举个例子

n=6, k=3, m=16, 反向环路径依次是

4: (5,0),(5,1),(5,1),(5,1),(0,0),(0,1),(0,1),(0,2),(1,0),(1,1),(1,1),(2,0),(2,1),(2,2),(3,0),(3,1),(3,2),(3,3),(3,3),(3,1),(4,0),(4,1),
3: (5,0),(5,1),(5,1),(0,0),(0,1),(0,2),(1,0),(1,1),(2,0),(2,1),(3,0),(3,1),(3,2),(3,3),(3,1),(4,0),
2: (5,0),(5,1),(0,0),(0,1),(1,0),(1,1),(2,0),(3,0),(3,1),(3,2),(3,1),(4,0),
1: (5,0),(0,0),(0,1),(1,0),(2,0),(3,0),(3,1),(3,1),(4,0),
0: (0,0),(1,0),(2,0),(3,0),(3,1),(4,0),

复杂度

整个处理过程的复杂度取决于反向处理的次数,每次处理掉(L-1)/(k+1)+n个点,总点数是1+(k+1)*m, 显然当n=1, k,m取最大值时,处理次数最多

根据题目给的范围 k<=10000, m<=1000000000, 可以通过程序计算出最多次数大约为~=213015, 比倍增的效果好

经验:把增环这个不容易直观分析的结构转化为路径这样可以简单处理的结构是个不错的思路

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值