zoukankan      html  css  js  c++  java
  • [算法模版]同余最短路

    [算法模版]同余最短路

    算法描述

    当我们解决形如(sum_{i=1}^n a_ix_i=k)的时候,我们可以使用同余最短路来解决。

    我们选择一个最小的(a_i)作为base,然后把其他的(a)表示成(base*p+left)的形式。

    我们定义(f[i])代表凑出(mod base)(i)的数最小需要多少个(base)

    而一个数(p)能被凑出当且仅当(f[pmod base]leq frac {p}{base})

    for(int i=0;i<base;i++){
        add(i,(i+a1)%base,a1);
        add(i,(i+a2)%base,a2);
    }
    

    一些疑问

    f[i]不会炸ll吗?

    我们把(mod base)的剩余系考虑成一个环,那么(f[i])代表在换上转几次圈才能走到(i)这个点。每次走的步数可以在序列(a)中任意选择一个。

    我们会发现,要让所有(f[i])最小,那我们每次走都应该是从一个走过的点走到一个没有走到过的点。如果走了一段时间,发现不管从环上哪个点走,走多少步,都无法到达一个没到达过的点。这种情况下,没到达过的点就永远不能到达了。

    所以走的次数的上界就是最大的(a)

    因为如果把最大的(a)取为(base)(虽然这样复杂度不是最优的,但是我们可以这样来计算上界)。那么每走一圈都最少会新到达一个点。所以要取遍剩余系就最多需要走(a_{max})次。

    为什么要选最小的(a)作为模数?

    显然,这样可以保证点数最小(剩余系最小)。

    另一种方法

    上一种方法虽然可以针对元素大小超过(10^{18})的情况,但是很容易会写炸。

    于是我用了另一种方法:(f[i])记录凑出(mod base)(i)最小的数是多少。

    这样虽然要求元素小于(10^9),但是好实现多了。

  • 相关阅读:
    安装mysql Install/Remove of the Service Denied!错误的解决办法
    Oracle新建Schema
    TOMCAT虚拟路径配置
    Java的基本数据类型与转换
    _web基础_servlet基础
    布局的嵌套
    使用BootStrap网格布局进行一次演示
    BootStrap导入及其使用
    路由
    AngularJs MVC 详解
  • 原文地址:https://www.cnblogs.com/GavinZheng/p/11709153.html
Copyright © 2011-2022 走看看