墨墨的等式(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;
}
發佈了31 篇原創文章 · 獲贊 3 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章