BZOJ2118 墨墨的等式[同余类最短路]

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


$O(mnlogm)$同余最短路做法:

首先不妨抽出最小的$a_i=m$,那么剩余的$a$如果可以表示出$x$,那么$x+km$的所有数都可以表出。所以对于$m$的同一个同余类$i\in[0,m)$,我们希望求出$f_i=\min\{h|h\mod=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(mnlogm)$的。由于O2dij优秀的速度所以可过。。。但是实际存在一种更快的$O(mn)$解法,我暂不甚理解,要先咕咕咕了。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<cmath>
 6 #include<queue>
 7 #define dbg(x) cerr << #x << " = " << x <<endl
 8 using namespace std;
 9 typedef long long ll;
10 typedef double db;
11 typedef pair<ll,int> pii;
12 template<typename T>inline T _min(T A,T B){return A<B?A:B;}
13 template<typename T>inline T _max(T A,T B){return A>B?A:B;}
14 template<typename T>inline char MIN(T&A,T B){return A>B?(A=B,1):0;}
15 template<typename T>inline char MAX(T&A,T B){return A<B?(A=B,1):0;}
16 template<typename T>inline void _swap(T&A,T&B){A^=B^=A^=B;}
17 template<typename T>inline T read(T&x){
18     x=0;int f=0;char c;while(!isdigit(c=getchar()))if(c=='-')f=1;
19     while(isdigit(c))x=x*10+(c&15),c=getchar();return f?x=-x:x;
20 }
21 const int N=5e5+7;
22 struct thxorz{int to,nxt,w;}G[N*11];
23 int Head[N],tot;
24 int n,m,a[13],c=1145141919;
25 ll L,R,ans;
26 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;}
27 priority_queue<pii,vector<pii>,greater<pii> > q;
28 ll dis[N];
29 #define y G[j].to
30 inline void dij(){
31     memset(dis,0x3f,sizeof dis);q.push(make_pair(dis[0]=0,0));
32     while(!q.empty()){
33         int x=q.top().second;ll d=q.top().first;q.pop();
34         if(d^dis[x])continue;
35         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));
36     }
37 }
38 #undef y
39 int main(){//freopen("test.in","r",stdin);//freopen("test.ans","w",stdout);
40     read(m),read(L),read(R);
41     for(register int i=1,x;i<=m;++i)read(x),x&&MIN(c,a[++n]=x);
42     for(register int i=0;i<c;++i)
43         for(register int j=1;j<=n;++j)if(a[j]^c)Addedge(i,(i+a[j])%c,a[j]);
44     dij();//for(register int i=0;i<c;++i)printf("%d %d\n",i,dis[i]);
45     for(register int i=0;i<c;++i)ans+=(dis[i]<=R?1+(R-dis[i])/c:0)-(dis[i]<=L-1?1+(L-1-dis[i])/c:0);
46     return printf("%lld\n",ans),0;
47 }
View Code

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

转载于:https://www.cnblogs.com/saigyouji-yuyuko/p/11606105.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值