zoukankan      html  css  js  c++  java
  • BZOJ2118:墨墨的等式(最短路)

    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。

    Solution 

    看样子好像是一个很经典的题……

    一开始读错题了难受了好久……后来发现题意可以化简成你有若干种价值为正的物品,每种无限个,问你给定区间$[B_{Min},B_{Max}]$中有多少个价值可以被凑出来。

    设$Min=min(a_i)$,那么显然对于$val∈[0,Min-1]$,若价值$val$能被凑出来,那么$val+?*Min$也能被凑出来。

    现在问题转化成了对于$val∈[0,Min-1]$,分别求最小可以被凑出来的$val+?*Min$。

    这个问题就可以转化成最短路来求解了,对于每一个$val$,我们枚举$i$,然后添加一条边$val->(val+a_i)modMin$,边长为$a_i$,然后求解最短路就好了。

    不懂的话画个图感性理解或者看看代码应该挺好用的

    Code

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 #include<queue>
     5 #define N (6000009)
     6 using namespace std;
     7 
     8 struct Edge{int to,next,len;}edge[N];
     9 struct Node
    10 {
    11     long long num,dis;
    12     bool operator < (const Node a) const {return dis>a.dis;}
    13 };
    14 int n,a[N],head[N],num_edge,Min=1e9;
    15 long long dis[N],Bmin,Bmax;
    16 bool vis[N];
    17 priority_queue<Node>q;
    18 
    19 void add(int u,int v,int l)
    20 {
    21     edge[++num_edge].to=v;
    22     edge[num_edge].next=head[u];
    23     edge[num_edge].len=l;
    24     head[u]=num_edge;
    25 }
    26 
    27 void Dijkstra(int s)
    28 {
    29     for (int i=0; i<Min; ++i) dis[i]=1e18;
    30     dis[s]=0; q.push((Node){s,0});
    31     while (!q.empty())
    32     {
    33         Node x=q.top(); q.pop();
    34         if (vis[x.num]) continue;
    35         vis[x.num]=true;
    36         for (int i=head[x.num]; i; i=edge[i].next)
    37             if (dis[x.num]+edge[i].len<dis[edge[i].to])
    38             {
    39                 dis[edge[i].to]=dis[x.num]+edge[i].len;
    40                 q.push((Node){edge[i].to,dis[edge[i].to]});
    41             }
    42     }
    43 }
    44 
    45 long long Calc(long long x)
    46 {
    47     long long ans=0;
    48     for (int i=0; i<Min; ++i)
    49         if (dis[i]<=x) ans+=(x-dis[i])/Min+1;
    50     return ans;
    51 }
    52 
    53 int main()
    54 {
    55     scanf("%d%lld%lld",&n,&Bmin,&Bmax);
    56     for (int i=1; i<=n; ++i)
    57     {
    58         scanf("%d",&a[i]);
    59         if (a[i]==0) {--i; --n; continue;}
    60         Min=min(Min,a[i]);
    61     }
    62     if (!n) {puts("0"); return 0;}
    63     for (int i=1; i<=n; ++i)
    64         for (int j=0; j<Min; ++j)
    65             add(j,(j+a[i])%Min,a[i]);
    66     Dijkstra(0);
    67     printf("%lld
    ",Calc(Bmax)-Calc(Bmin-1));
    68 }
  • 相关阅读:
    Python基础知识大总结
    Python基础教程第一章 python基础知识
    XDUOJ 1000-1002题解
    C# PDF格式 下载
    C# 文件(图片)下载
    C# DataTable转List
    C# Excel导入与导出
    C# 文件压缩与解压
    C# 文件流 导入 导出
    C# lambda表达式
  • 原文地址:https://www.cnblogs.com/refun/p/9606089.html
Copyright © 2011-2022 走看看