題目描述
墨墨突然對等式很感興趣,他正在研究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;
}