声明:关于这题的$O(mn)$尚且未深入理解,虽然之前有跟这位神仙聊过做法但并没太懂。。


$O(mn\log m)$同余最短路做法:

首先不妨抽出最小的$a_i=m$,那么剩余的$a$如果可以表示出$x$,那么$x+km$的所有数都可以表出。所以对于$m$的同一个同余类$i\in[0,m)$,我们希望求出$f_i=\min\{h|h\mod m=i\}$其中$h$是可以用其他$a$表出的,也就是用其他东西来表示出最小的、可以$\mod m=i$的数,这样,所有$h+km(k\in N)$都可以表示,而所有$h+km(k<0)$都不能表示。要求出这个数组,就需要使用这个同余类最短路算法,由背包DP的思路,对于其他一个不是$m$的$a$可以有$f_{(i+a)\mod m}=\min(f_i+a)$,也就是希望由其他最小值推得。那么对于$i\to (i+a)\mod m$建一条边权$a$的边,$f_0=0$,这样$f_i$如果要最小表示出来就是要从$f_0$找一条路到达他,加上路上边权最小,这个跑一遍最短路即可。

不过,有$m$个点,每个点有$n$个连边(有向),总边数$mn$,这个复杂度是$O(mn\log m)$的。由于O2dij优秀的常数所以可过。。。但是实际存在一种更快的$O(mn)$解法,我暂不甚理解,要先咕咕咕了。

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#define dbg(x) cerr << #x << " = " << x <<endl
using namespace std;
typedef long long ll;
typedef double db;
typedef pair<ll,int> pii;
template<typename T>inline T _min(T A,T B){return A<B?A:B;}
template<typename T>inline T _max(T A,T B){return A>B?A:B;}
template<typename T>inline char MIN(T&A,T B){return A>B?(A=B,):;}
template<typename T>inline char MAX(T&A,T B){return A<B?(A=B,):;}
template<typename T>inline void _swap(T&A,T&B){A^=B^=A^=B;}
template<typename T>inline T read(T&x){
x=;int f=;char c;while(!isdigit(c=getchar()))if(c=='-')f=;
while(isdigit(c))x=x*+(c&),c=getchar();return f?x=-x:x;
}
const int N=5e5+;
struct thxorz{int to,nxt,w;}G[N*];
int Head[N],tot;
int n,m,a[],c=;
ll L,R,ans;
inline void Addedge(int x,int y,int z){G[++tot].to=y,G[tot].nxt=Head[x],Head[x]=tot,G[tot].w=z;}
priority_queue<pii,vector<pii>,greater<pii> > q;
ll dis[N];
#define y G[j].to
inline void dij(){
memset(dis,0x3f,sizeof dis);q.push(make_pair(dis[]=,));
while(!q.empty()){
int x=q.top().second;ll d=q.top().first;q.pop();
if(d^dis[x])continue;
for(register int j=Head[x];j;j=G[j].nxt)if(MIN(dis[y],d+G[j].w))q.push(make_pair(dis[y],y));
}
}
#undef y
int main(){//freopen("test.in","r",stdin);//freopen("test.ans","w",stdout);
read(m),read(L),read(R);
for(register int i=,x;i<=m;++i)read(x),x&&MIN(c,a[++n]=x);
for(register int i=;i<c;++i)
for(register int j=;j<=n;++j)if(a[j]^c)Addedge(i,(i+a[j])%c,a[j]);
dij();//for(register int i=0;i<c;++i)printf("%d %d\n",i,dis[i]);
for(register int i=;i<c;++i)ans+=(dis[i]<=R?+(R-dis[i])/c:)-(dis[i]<=L-?+(L--dis[i])/c:);
return printf("%lld\n",ans),;
}

PS:由于图不是特殊构造的,所以spfa速度更快,但是是不是复杂度$O(mn)$我也不知道。。


20191008UPD

国庆期间由于某种机缘,我把这题不理解的$O(mn)$解法向$\text{zzq}$老师询问,然后可能是有一些明白了。。。

上面提到用$f$表示同余最小的表示数,其实就是类似于一个无限背包。每个新的$a_i$可以去刷表,也就是以前的$f_{i-1,j}$,然后不断的刷,各个$a$之间应当是相互独立的,更新顺序无所谓,并且每个$a$连边应当形成一些环,这些环也相互独立,是“全等”的。不过由于是环形的特殊结构,不能直接用背包的方法刷表,分析一下发现最小的那个不会被更新,于是找到每个环上最小的那个,开始向后做常规的无限背包,做一圈。zzq提出的方法是直接无脑绕两圈更新,实际上都是一样的道理。code的话。。不想写了。。可以参考上面那个神仙的代码。

BZOJ2118 墨墨的等式[同余类最短路]的更多相关文章

  1. Luogu4156 WC2016 论战捆竹竿 KMP、同余类最短路、背包、单调队列

    传送门 豪华升级版同余类最短路-- 官方题解 主要写几个小trick: \(1.O(nm)\)实现同余类最短路: 设某一条边长度为\(x\),那么我们选择一个点,在同余类上不断跳\(x\),可以形成一 ...

  2. Bzoj2118 墨墨的等式

    Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 1488  Solved: 578 Description 墨墨突然对等式很感兴趣,他正在研究a1x1+ ...

  3. BZOJ2118: 墨墨的等式(同余类BFS)(数学转为图论题)

    2118: 墨墨的等式 Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 2944  Solved: 1206[Submit][Status][Discu ...

  4. BZOJ2118: 墨墨的等式(最短路构造/同余最短路)

    Description 墨墨突然对等式很感兴趣,他正在研究a1x1+a2y2+…+anxn=B存在非负整数解的条件,他要求你编写一个程序,给定N.{an}.以及B的取值范围,求出有多少B可以使等式存在 ...

  5. 【BZOJ2118】墨墨的等式(最短路)

    [BZOJ2118]墨墨的等式(最短路) 题面 BZOJ 洛谷 题解 和跳楼机那题是一样的. 只不过走的方式从\(3\)种变成了\(n\)种而已,其他的根本没有区别了. #include<ios ...

  6. 【BZOJ2118】墨墨的等式 最短路

    [BZOJ2118]墨墨的等式 Description 墨墨突然对等式很感兴趣,他正在研究a1x1+a2y2+…+anxn=B存在非负整数解的条件,他要求你编写一个程序,给定N.{an}.以及B的取值 ...

  7. BZOJ2118: 墨墨的等式(最短路 数论)

    题意 墨墨突然对等式很感兴趣,他正在研究a1x1+a2y2+…+anxn=B存在非负整数解的条件,他要求你编写一个程序,给定N.{an}.以及B的取值范围,求出有多少B可以使等式存在非负整数解. So ...

  8. 【同余最短路】【例题集合】洛谷P3403 跳楼机/P2371 墨墨的等式

    接触到的新内容,[同余最短路]. 代码很好写,但思路不好理解. 同余最短路,并不是用同余来跑最短路,而是通过同余来构造某些状态,从而达到优化时间空间复杂度的目的.往往这些状态就是最短路中的点,可以类比 ...

  9. BZOJ2118墨墨的等式[数论 最短路建模]

    2118: 墨墨的等式 Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 1317  Solved: 504[Submit][Status][Discus ...

随机推荐

  1. Go语言实例化结构体——为结构体分配内存并初始化

    转自: http://c.biancheng.net/view/66.html 结构体的定义只是一种内存布局的描述,只有当结构体实例化时,才会真正地分配内存.因此必须在定义结构体并实例化后才能使用结构 ...

  2. ULB

    https://docs.ucloud.cn/network/ulb/intro/whatisulb 创建ulb ulb里创建vserver, 设置监听端口 配置后端转发节点(服务节点) 在服务节点上 ...

  3. kafka原理和操作

    参考: 原理: https://www.cnblogs.com/yinzhengjie/p/9780976.html 常用配置参数: https://www.cnblogs.com/yinzhengj ...

  4. 【转帖】k8s-kubectl命令大全

    https://www.cnblogs.com/fuyuteng/p/9458282.html 学习一下 Kubectl命令行管理对象 类型 命令 描述 基础命令 create 通过文件名或标准输入创 ...

  5. NOIP模拟赛 打铁的匠 题解

    [问题描述] Mark Douglas是一名优秀的锻造师.与他优秀的锻造水平不相符,他非常穷,以至于很多好刀都因为缺少素材缺少资金无法打造. Mark把他有能力锻造的所有n种刀建成了一棵锻造树,除了第 ...

  6. selenium爬取斗鱼所有直播房间信息

    还是分析一下大体的流程: 首先还是Chrome浏览器抓包分析元素,这是网址:https://www.douyu.com/directory/all 发现所有房间的信息都是保存在一个无序列表中的li中, ...

  7. Java 线程控制

    一.线程控制 和线程相关的操作都定义在Thread类中,但在运行时可以获得线程执行环境的信息.比如查看可用的处理器数目(这也行?): public class RunTimeTest { public ...

  8. 【IntelliJ IDEA】tomcat启动,打印日志乱码问题 【最新解决方法请看最后附录】

    刚开始给idea上配置了一个tomcat,然后跟着http://wiki.jikexueyuan.com/project/intellij-idea-tutorial/theme-settings.h ...

  9. C# 使用Emit实现动态AOP框架 进阶篇之优化

    目  录 C# 使用Emit实现动态AOP框架 (一) C# 使用Emit实现动态AOP框架 (二) C# 使用Emit实现动态AOP框架 (三) C# 使用Emit实现动态AOP框架 进阶篇之异常处 ...

  10. 文件名后面加(1).text

    ; //在重复名称后加(序号) while (File.Exists(path)) { if (path.Contains(").")) { int start = path.La ...