• [spfa] Bzoj 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

    【数据规模】
      对于20%的数据,N≤5,1≤BMin≤BMax≤10。
      对于40%的数据,N≤10,1≤BMin≤BMax≤10^6。
      对于100%的数据,N≤12,0≤ai≤4*10^5,1≤BMin≤BMax≤10^12。

    题解

    • 我们设a1表示a数组中最小的元素,dis[i]表示我通过使用若干个数,使得结果模a1=i,假设结果为x*a1+i,最小的x是多少

    • 那么我们可以连边后求最短路来求出dis数组,最后统计答案即可

    • 在做物品无限的背包问题时,可以把问题转换成对某个值取模后求最短路

    • 新姿势get√

    代码

     1 #include <cstdio>
     2 #include <iostream>
     3 #include <cstring>
     4 #include <queue>
     5 #include <algorithm> 
     6 using namespace std;
     7 #define ll long long
     8 const int N=500010;
     9 int n,cnt,head[N],a[20];
    10 ll l,r,ans,dis[N];
    11 bool vis[N];
    12 struct edge{int to,from;ll v;}e[N*12];
    13 queue<int>Q;
    14 void insert(int x,int y,int v) { e[++cnt].to=y,e[cnt].from=head[x],e[cnt].v=v,head[x]=cnt; }
    15 void spfa()
    16 {
    17     Q.push(0),vis[0]=1;
    18     while (!Q.empty())
    19     {
    20         int u=Q.front(); Q.pop();
    21         for (int i=head[u];i;i=e[i].from)
    22             if (dis[u]+e[i].v<dis[e[i].to]) 
    23             {
    24                 dis[e[i].to]=dis[u]+e[i].v;
    25                 if (!vis[e[i].to]) vis[e[i].to]=1,Q.push(e[i].to);
    26             }
    27         vis[u]=0;
    28     }
    29 }
    30 int main()
    31 {
    32     scanf("%d%lld%lld",&n,&l,&r);
    33     for (int i=1;i<=n;i++) scanf("%d",&a[i]);
    34     sort(a+1,a+n+1),dis[0]=0;
    35     for (int i=1;i<a[1];i++) dis[i]=(ll)1e12;
    36     for (int i=2;i<=n;i++) for (int j=0;j<a[1];j++) insert(j,(j+a[i]%a[1])%a[1],a[i]/a[1]+(j+a[i]%a[1]>=a[1]));
    37     spfa(),ans=0;
    38     for (int i=0;i<a[1];i++) ans+=max((r-i-a[1]*max((ll)0,dis[i]-1))/a[1],(ll)0)-max((l-1-i-a[1]*max((ll)0,dis[i]-1))/a[1],(ll)0);
    39     printf("%lld",ans);
    40 }
  • 相关阅读:
    网络编程-python实现-UDP(1.1.2)
    网络编程-python实现-socket(1.1.1)
    1-浮动布局
    1-解决java Scanner出现 java.util.NoSuchElementException
    1.激活函数
    A-交叉熵的使用
    matplotlib的学习16-animation动画
    matplotlib的学习15-次坐标轴
    matplotlib的学习14-图中图
    07-爬虫验证码破解实战
  • 原文地址:https://www.cnblogs.com/Comfortable/p/11138772.html
Copyright © 2020-2023  润新知