zoukankan      html  css  js  c++  java
  • 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
    ",nr-nl);
    }
    
  • 相关阅读:
    poj 2485 Highways 最小生成树
    hdu 3415 Max Sum of MaxKsubsequence
    poj 3026 Borg Maze
    poj 2823 Sliding Window 单调队列
    poj 1258 AgriNet
    hdu 1045 Fire Net (二分图匹配)
    poj 1789 Truck History MST(最小生成树)
    fafu 1181 割点
    减肥瘦身健康秘方
    人生的问题
  • 原文地址:https://www.cnblogs.com/AGFghy/p/9366363.html
Copyright © 2011-2022 走看看