【BZOJ2118】—墨墨的等式(最短路+背包)
考虑到其实这就是一个背包问题,但是发现的范围太大了
考虑另外的做法
我们发现对于一个数,如果可以凑出来,那么显然都可以凑出来
而且可以凑出个
为了让求的量最少,我们用最小的
那么那现在我们也就只需要找到最小的满足就可以了
发现可以最短路求
那就跑求出所有最小的就可以了
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register
const ll inf=1e13;
inline ll read(){
char ch=getchar();
ll res=0;
while(!isdigit(ch))ch=getchar();
while(isdigit(ch)) res=(res<<3)+(res<<1)+(ch^48),ch=getchar();
return res;
}
const int N=500005;
int vis[N],a[N],n,mox;
ll L,R,dis[N];
inline void spfa(){
queue<int> q;
vis[0]=1,dis[0]=0;
q.push(0);
while(!q.empty()){
int u=q.front();q.pop(),vis[u]=0;
for(int i=1;i<=n;i++){
int v=(u+a[i])%mox;
if(dis[u]+a[i]<dis[v]){
dis[v]=dis[u]+a[i];
if(!vis[v]){
q.push(v),vis[v]=1;
}
}
}
}
}
inline ll calc(ll mx){
ll ans=0;
for(int i=0;i<mox;i++){
if(dis[i]<=mx)
ans+=(mx-dis[i])/mox+1;
}
return ans;
}
int main(){
n=read(),L=read(),R=read();
mox=1e9;
for(int i=1;i<=n;i++){
a[i]=read();
if(a[i]==0){i--,n--;continue;}
mox=min(mox,a[i]);
}
memset(dis,127/3,sizeof(dis));
spfa();
cout<<calc(R)-calc(L-1);
}