题目描述
墨墨突然对等式很感兴趣,他正在研究a1x1+a2y2+…+anxn=B存在非负整数解的条件,他要求你编写一个程序,给定N、{an}、以及B的取值范围,求出有多少B可以使等式存在非负整数解。
输入
输入的第一行包含3个正整数,分别表示N、BMin、BMax分别表示数列的长度、B的下界、B的上界。
输入的第二行包含N个整数,即数列{an}的值。
输出
输出一个整数,表示有多少b可以使等式存在非负整数解。
样例输入
2 5 10
3 5
样例输出
5
提示
对于20%的数据,N≤5,1≤BMin≤BMax≤10。
对于40%的数据,N≤10,1≤BMin≤BMax≤10^6。
对于100%的数据,N≤12,0≤ai≤4*10^5,1≤BMin≤BMax≤10^12。
想法
- 对于一个a1 a1*k+x=B存在整数解 则a1*(k+1)+x=B’依然存在整数解
- 因此我们对于一个a1 如果求出0到a1-1所有数对应式子中最小的k就能求出所有整数解
- 求k的方法 采用最短路的方法
算法
- 与想法相同找出a值中最小的一个 将0到a1-1所有数转化成一个点
- dijkstra+堆优化
代码
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <string>
#include <queue>
#define MAXN 400005
using namespace std;
typedef long long ll;
int N,a[15],tot,head[MAXN];
ll low,up,dist[MAXN],ans;
struct iNode
{
int u,v,next;
ll w;
}edge[MAXN<<1];
struct Node
{
int pos;
ll v;
Node(){};
Node(int _pos,ll _v){pos=_pos;v=_v;}
bool operator<(const Node &rhs)const
{
return v>rhs.v;
}
};
priority_queue<Node >heap;
inline void add(int u,int v,ll w)
{
edge[tot].u=u,edge[tot].v=v,edge[tot].w=w,edge[tot].next=head[u],head[u]=tot++;
}
inline void put(int a)
{
for (int i=head[a];i!=-1;i=edge[i].next)
{
if(dist[edge[i].v]==-1)
{
heap.push(Node(edge[i].v,dist[a]+edge[i].w));
}
}
}
inline void dijkstra()
{
memset(dist,-1,sizeof(dist));
dist[0]=0;
put(0);
int p;
while(!heap.empty())
{
if(dist[heap.top().pos]!=-1)
{
heap.pop();
continue;
}
p=heap.top().pos;
dist[p]=heap.top().v;
heap.pop();
put(p);
}
}
int main()
{
//freopen("equ.in","r",stdin);
//freopen("equ.out","w",stdout);
memset(head,-1,sizeof(head));
scanf("%d%lld%lld",&N,&low,&up);
low-=1;
for (int i=1;i<=N;i++)
{
scanf("%d",&a[i]);
if(a[i]<a[1])swap(a[i],a[1]);
}
//sort(a+1,a+1+N);
for (int i=0;i<a[1];i++)
for (int j=2;j<=N;j++)
add(i,(i+a[j])%a[1],(i+a[j])/a[1]);
dijkstra();
for (int i=0;i<a[1];i++)
{
if(dist[i]==-1)continue;
ans+=max(0ll,(up-i)/a[1]-max(0ll,max((ll)(low-i)/a[1],dist[i]-1)));
}
cout<<ans<<endl;
return 0;
}