墨墨突然对等式很感兴趣,他正在研究
a1x1+a2x2+...+anxn=B存在非负整数解的条件
他要求你编写一个程序 ,给定N、{an}、 以及B的取值范围
求出有多少B可以使等式存在非负整数解
集训队的神题……
怎么看都以为是数论题,结果是同余最短路……
通过对所有数%k,跑最短路,求出在%k意义下的最小数
那么在%k意义下的更大的数也一定可以抵达
而且有点卡常,所以跑spfa的时候不用建边,直接跑就好了
实乃思维神题啊……
代码:
#include<bits/stdc++.h>
#define N 500005
#define inf (1LL<<60)
#define ll long long
using namespace std;
ll n,l,r,a[13],ans=0;
template<class T>inline void read(T &res)
{
char c;T flag=1;
while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;res=c-'0';
while((c=getchar())>='0'&&c<='9')res=res*10+c-'0';res*=flag;
}
ll dis[N];
bool vis[N];
queue<ll> q;
void spfa(int s)
{
for(register int i=0;i<=a[1];++i) dis[i]=inf;
memset(vis,0,sizeof(vis));
q.push(s);
dis[s]=0;
vis[s]=1;
while(!q.empty())
{
int u=q.front();q.pop();vis[u]=0;
for(register int i=2;i<=n;++i)
{
int v=(u+a[i])%a[1];
if(dis[v]>dis[u]+a[i])
{
dis[v]=dis[u]+a[i];
if(!vis[v])
{
q.push(v);
vis[v]=1;
}
}
}
}
}
int main()
{
read(n);read(l);read(r);
for(register int i=1;i<=n;++i) read(a[i]);
sort(a+1,a+n+1);
spfa(0);
for(register int i=0;i<a[1];++i)
{
if(dis[i]<=r)
{
if(dis[i]>=l) ans+=(r-dis[i])/a[1]+1;
else ans+=(r-dis[i])/a[1]+1,ans-=(l-dis[i]+a[1]-1)/a[1];
}
}
printf("%lld
",ans);
return 0;
}