https://www.lydsy.com/JudgeOnline/problem.php?id=2118
由于Bmi,Bmx太大,背包显然是不行的
我们考虑B对于a[1]取余,B=a[1]*x1+b(b=0,1,....a[1]-1)。
那么我们只要知道对于每一个b,最小体积是多少时能到达它就行了,之后就可以通过不断加a[1]来得到其他值。
那么我们对每一个b,连一条边到(b+a[1])%a[1],由于只有N<=12种数字,那么最多就N*A[1]条边,跑最短路即可。
#include<bits/stdc++.h>
using namespace std;
const int maxl=5e5+10;
int n,cnt;
int ehead[maxl];
long long bmi,bmx,ans;
long long a[maxl],dis[maxl];
bool vis[maxl];
struct ed
{
int to,nxt,l;
}e[maxl*10*2];
typedef pair<long long,int> p;
priority_queue<p,vector<p>,greater<p> >q;
inline void add(int u,int v,int l)
{
e[++cnt].to=v;e[cnt].l=l;
e[cnt].nxt=ehead[u];ehead[u]=cnt;
}
inline void prework()
{
scanf("%d%lld%lld",&n,&bmi,&bmx);
for(int i=1;i<=n;i++)
scanf("%lld",&a[i]);
cnt=0;
for(int i=0;i<a[1];i++)
for(int j=2;j<=n;j++)
add(i,(i+a[j])%a[1],a[j]);
}
inline void mainwork()
{
memset(dis,0x3f,sizeof(long long)*a[1]);
dis[0]=0;q.push(make_pair(0,0));
p d;int u,v;
while(!q.empty())
{
d=q.top();q.pop();
u=d.second;
if(d.first!=dis[u])
continue;
vis[u]=true;
for(int i=ehead[u];i;i=e[i].nxt)
{
v=e[i].to;
if(vis[v]) continue;
if(dis[u]+e[i].l<dis[v])
{
dis[v]=dis[u]+e[i].l;
q.push(make_pair(dis[v],v));
}
}
}
ans=0;
for(int i=0;i<a[1];i++)
if(dis[i]<bmi)
ans+=(bmx-dis[i])/a[1]-(bmi-1-dis[i])/a[1];
else if(dis[i]<=bmx)
ans+=(bmx-dis[i])/a[1]+1;
}
inline void print()
{
printf("%lld",ans);
}
int main()
{
prework();
mainwork();
print();
return 0;
}