墨墨的等式(equ)题解

题目描述

墨墨突然对等式很感兴趣,他正在研究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;
}

你可能感兴趣的:(墨墨的等式(equ)题解)