[bzoj2118]墨墨的等式

来源:互联网 发布:英国商科大学排名 知乎 编辑:程序博客网 时间:2024/04/30 02:25

2118: 墨墨的等式

Time Limit: 10 Sec Memory Limit: 259 MB
Submit: 878 Solved: 337
[Submit][Status][Discuss]
Description

墨墨突然对等式很感兴趣,他正在研究a1x1+a2y2+…+anxn=B存在非负整数解的条件,他要求你编写一个程序,给定N、{an}、以及B的取值范围,求出有多少B可以使等式存在非负整数解。

Input

输入的第一行包含3个正整数,分别表示N、BMin、BMax分别表示数列的长度、B的下界、B的上界。输入的第二行包含N个整数,即数列{an}的值。

Output

输出一个整数,表示有多少b可以使等式存在非负整数解。

Sample Input

2 5 10

3 5

Sample Output

5

HINT

对于100%的数据,N≤12,0≤ai≤5*10^5,1≤BMin≤BMax≤10^12。

设最小的点是x,如果y能被凑出来,那么y+x就也能被凑出来。
这样把每个点模x之后,用模后的数在0~n-1的点上建图,这样跑出来从0到每个点的最短路的长度就是最初到达这个点需要的大小,然后再利用模的数算答案就行了。

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;#define LL long long#define inf 0x7ffffffffffffconst int N=500010; bool f[N];struct S{int st,en;LL va;}aa[N*15];int n,point[N],next[N*15],tot,l[N];LL bmin,bmax,a[20],dis[N];inline void add(int x,int y,LL z){    tot+=1;next[tot]=point[x];point[x]=tot;    aa[tot].st=x;aa[tot].en=y;aa[tot].va=z;}inline void SPFA(){    int h=0,t=1,u,i;    for(i=0;i<=a[1];++i) dis[i]=inf,f[i]=1;    l[h]=0;dis[0]=0;    while(h!=t){        h=h%a[1]+1;u=l[h];f[u]=true;        for(i=point[u];i;i=next[i])          if(dis[aa[i].en]>dis[u]+aa[i].va){            dis[aa[i].en]=dis[u]+aa[i].va;            if(f[aa[i].en]){                f[aa[i].en]=false;                t=t%a[1]+1;                l[t]=aa[i].en;            }          }    }dis[0]=a[1];}int main(){    int i,j;    scanf("%d%lld%lld",&n,&bmin,&bmax);    for(i=1;i<=n;++i) scanf("%lld",&a[i]);    sort(a+1,a+n+1);    for(i=0;i<a[1];++i)      for(j=1;j<=n;++j) add(i,(i+a[j])%a[1],a[j]);    SPFA();    LL ans=0,x,y;    for(i=0;i<a[1];++i)      if(dis[i]<=bmax){        x=max(0LL,(bmin-dis[i])/a[1]);        y=(bmax-dis[i])/a[1];        if(x*a[1]+dis[i]<bmin) x+=1;        if(y*a[1]+dis[i]>bmax) y-=1;        ans+=y-x+1;      }    printf("%lld\n",ans);}
0 1
原创粉丝点击