zoukankan      html  css  js  c++  java
  • 【BZOJ 2118】 墨墨的等式(Dijkstra)

    BZOJ2118 墨墨的等式

    题链:http://www.lydsy.com/JudgeOnline/problem.php?id=2118

    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*105,1≤BMin≤BMax≤1012

    题解

    假设x是一个可以被拼出的可行解,那么(x+k*a[i])必然也是可行解,那么我们把a[i]设为最小的a[0]即可,因为这样才能使得k最大。同时我们可以得到:

    1. x可以写成k*a[0]+i,(0<=i<a[0])
    2. 所以最多只有i个解,我们只需求出每个解的最小代价即可
      因此可以建图,每个i与(a[j]+i)%a[0],之间的代价为a[j],之后再求0到每个i之间的距离即可

    参考代码

    #include <queue>
    #include <cmath>
    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <iostream>
    #include <algorithm>
    #include <vector>
    #define ll long long
    #define inf 10000000000000
    #define mod 1000000007
    using namespace std;
    ll read()
    {
        ll x=0,f=1;
        char ch=getchar();
        while(ch<'0'||ch>'9')
        {
            if(ch=='-')f=-1;
            ch=getchar();
        }
        while(ch>='0'&&ch<='9')
        {
            x=x*10+ch-'0';
            ch=getchar();
        }
        return x*f;
    }
    const int N=5e5+10;
    const int M=5e6+10;
    int cnt;
    struct Edge{
        int cost,to,nxt;
        Edge(){};
        Edge(int tc,int tt,int tn=0):cost(tc),to(tt),nxt(tn){}
        bool operator < (const Edge &an) const{
            return cost>an.cost;
        }
    }Path[M];
    int a[20],head[N];
    ll dis[N];
    bool vis[N];
    void Addedge(int u,int v,int w){
    	Path[cnt]=(Edge){w,v,head[u]};
    	head[u]=cnt++;
    }
    void Dijkstra()
    {
        priority_queue<Edge>que;
    	for(int i=0;i<a[0];i++) dis[i]=inf;
    	dis[0]=0;
    	que.push(Edge(0,0));
    	while(!que.empty()){
    		int cur=que.top().to;que.pop();
    		if(vis[cur])continue;
    		vis[cur]=true;
    		for(int i=head[cur];i;i=Path[i].nxt)
    			if(dis[cur]+Path[i].cost<dis[Path[i].to]){
    				dis[Path[i].to]=dis[cur]+Path[i].cost;
    				que.push(Edge(dis[Path[i].to],Path[i].to));
    			}
    	}
    }
    ll query(ll x)
    {
        ll ans=0;
        for (int i=0;i<a[0];i++)
            if (dis[i]<=x) ans+=(x-dis[i])/a[0]+1;
        return ans;
    }
    void Init(){
        cnt=1;
        memset(head,0,sizeof(head));
    }
    int main(){
        int top=0,n=read();
        ll l=read(),r=read();
        Init();
        for(int i=0;i<n;i++){
             int x=read();
             if(x==0) continue;
             a[top++]=x;
        }
        sort(a,a+top);
        for(int i=0;i<a[0];i++){
            for(int j=1;j<top;j++){
                 Addedge(i,(a[j]+i)%a[0],a[j]);
            }
        }
        Dijkstra();
        printf("%lld
    ",query(r)-query(l-1));
        return 0;
    }
    
    
  • 相关阅读:
    Linux crontab定时执行任务 命令格式与详细例子
    git的color configura
    Linux不用使用软件把纯文本文档转换成PDF文件的方法
    linux sar命令详细说明相关参数
    linux下sar tool command note
    Linux see 网卡当前流量
    安装调试Installing Odoo
    寻找[nginx] 由Lua 粘合的Nginx生态环境-- agentzh
    git检查与放弃本地的代码修改情况
    发现linux shell中$0,$?,$!等的特殊用法
  • 原文地址:https://www.cnblogs.com/zsyacm666666/p/6957224.html
Copyright © 2011-2022 走看看