同余最短路小结

介绍

不记得是从哪里看到的好东西了qwq

这个东西用来做这种类型的问题:给出若干个数,每个数有无限个,问用这些数能组成(加起来)多少个不同的数。

当然,也可以求出某个具体的数能不能被这若干个数组成,也有其他能解决的问题,因为实际上这个东西是处理出了一个 f f f 数组,活用这个数组可以做很多事。

求解

假设你现在有 a 1 a_1 a1 ~ a n a_n an n n n 个数,首先要任选一个数作为模数,设为 p p p,然后 f [ i ] f[i] f[i] 的定义为:用其他数能组成的 模 p p p 等于 i i i 的 最小的数。

比如说,有三个数 5 , 7 , 9 5,7,9 5,7,9,设 p = 5 p=5 p=5,那么 f [ 1 ] = 7 + 9 = 16 f[1]=7+9=16 f[1]=7+9=16,虽然 7 + 7 + 7 = 21   m o d   5 = 1 7+7+7=21 \bmod 5=1 7+7+7=21mod5=1,但是 16 16 16 21 21 21 小,所以要 16 16 16

可以发现, f [ i ] f[i] f[i] 有这样的转移方程: f [ ( i + a [ j ] )   m o d   a [ 1 ] ] = f [ i ] + a [ j ] f[(i+a[j])\bmod a[1]]=f[i]+a[j] f[(i+a[j])moda[1]]=f[i]+a[j],发现这个很像最短路的转移: f [ y ] = f [ x ] + c o s t f[y]=f[x]+cost f[y]=f[x]+cost,并且这里要求的也是所有转移中的最小值,和最短路的目的一样,所以可以将 i i i ( i + a [ j ] )   m o d   a [ 1 ] (i+a[j])\bmod a[1] (i+a[j])moda[1] 连边,代价为 a [ j ] a[j] a[j],然后跑一下最短路算法就能得到 f f f 了。

有了这个 f f f 之后,就能干很多事情,比如说判断一个数 x x x 能不能由 a 1 a_1 a1 ~ a n a_n an 组成,因为 f f f 中存的是最小值,所以如果 x x x f [ x   m o d   a [ 1 ] ] f[x\bmod a[1]] f[xmoda[1]] 大,而 f [ x   m o d   a [ 1 ] ] f[x\bmod a[1]] f[xmoda[1]] 可以由 a 2 a_2 a2 ~ a n a_n an 组成,并且 x   m o d   a [ 1 ] x\bmod a[1] xmoda[1] 加若干个 a [ 1 ] a[1] a[1] 能得到 x x x,所以 x x x 也可以由 a 1 a_1 a1 ~ a n a_n an 组成。

题表

其实都是差不多的题qwq……

洛谷 P3403 跳楼机   题解
[国家集训队]墨墨的等式   题解
[Poi2003]Sums   题解
洛谷 P2662 牛场围栏   题解

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值