BZOJ 2118: 墨墨的等式(最短路dijkstra+堆)


2118: 墨墨的等式

  Time Limit: 10 Sec
  Memory Limit: 259 MB

Description###

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

Input###

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

Output###

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

Sample Input 1###

  2 5 10
  3 5
  

Sample Output 1###

  5
  

HINT###

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

题目地址: BZOJ 2118: 墨墨的等式

题解:

     
  每个数都能表示成\(k*a[1]+x(0<=x<a[1])\)的形式
  如果对于每个\(x\)我们求出最小的\(k*a[1]+x\)
  那么把\([l,r]\)分成\([1,l-1]\)\([1,r]\)来做,就可以轻松统计答案
  问题就变成了如何求出最小的\(k*a[1]+x\)
  把每个\(x\)都当做一个点
  只需在\(x\)\((x+a[j])\) mod \(a[1]\)之间连一条边权为\(a[j]\)的边,再跑一遍最短路即可
www.cnblogs.com/AGFghy/


AC代码

#include<cstdio>
#include<algorithm>
#include<queue>
#define pa pair<ll,int>
using namespace std;
typedef long long ll;
int n,num,now;
int len[6000005],point[6000005],next[6000005],p[500005],head[500005],a[20];
ll d[500005];
ll l,r,nl,nr;
void insert(int u,int v,int l)
{
	num++; len[num]=l; point[num]=v; next[num]=head[u]; head[u]=num;
}
void Dijkstra(int x)
{
	priority_queue<pa,vector<pa>,greater<pa> >q; 
    for (int i=0; i<=a[now]-1; i++)
        d[i]=(ll)1e60,p[i]=0;
    d[x]=0; q.push(make_pair(0,x));
    while (!q.empty())
    {
        int now=q.top().second; 
        p[now]=1;
        q.pop();
        for (int i=head[now]; i; i=next[i])
        {
            int v=point[i];
            if (p[v]) continue;
            if (d[now]+len[i]<d[v])
            {
                d[v]=d[now]+len[i];
                q.push(make_pair(d[v],v));
            }
        }
    }
}
int main()
{
	scanf("%d%lld%lld",&n,&l,&r);
	l--;
	for (int i=1; i<=n; i++)
		scanf("%d",&a[i]);
	sort(a+1,a+n+1);
	now=1;
	while (a[now]==0) now++;
	for (int i=0; i<=a[now]-1; i++)
		for (int j=2; j<=n; j++)
			insert(i,(i+a[j])%a[now],a[j]);
	Dijkstra(0);
	for (int i=0; i<=a[now]-1; i++)
		if (d[i]<=r)
		{
			if (l-d[i]>=0) nl+=((l-d[i])/a[now])+1;
			if (r-d[i]>=0) nr+=((r-d[i])/a[now])+1;
		}
	printf("%lld\n",nr-nl);
}
posted @ 2018-07-25 15:51  AGFghy  阅读(202)  评论(0编辑  收藏  举报