zoukankan      html  css  js  c++  java
  • 【BZOJ 2118】 2118: 墨墨的等式 (最短路)

    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*10^5,1≤BMin≤BMax≤10^12。

    Source

    【分析】

      看了好久题解,感觉好机智啊。。

      题目可以理解成经典的背包问题。只是他问你的是[L,R]区间中有多少个容积是恰好可以装满的。

      然后这个范围很大啊,传统的暴力当然是行不通的了。

      考虑一个可以被拼出来的x,他里面可以包含ai也可以不包含ai。设x%ai=b(0<=b<ai)

      那么其实x+ai都可以被拼出来,显然。

      所以我们只要对于一个b,求出最小的可以拼出来的x,那么一直加ai也是可以的。

      直接把不同的b算出来的答案加起来就好了。

      要证明的话只要说明两个东西:

      1、不重复性,对于不同的可以拼出的x1,x2,如果他们%ai不同,那就不会算重复。

        如果他们%ai相同,也不会算重复【233我在搞笑?】

      2、不遗漏性,对于可以拼出来的x1,有一个模对应的b,那么肯定会算到嘛= =【233

      所以就这样搞笑的证明了??

      【想出来的人思路真的很妙【我根本看不出是最短路啊ORZ。。。

     1 #include<cstdio>
     2 #include<cstdlib>
     3 #include<cstring>
     4 #include<iostream>
     5 #include<algorithm>
     6 #include<cmath>
     7 #include<queue>
     8 #include<vector>
     9 using namespace std;
    10 #define LL long long
    11 #define Maxm 7000100
    12 #define Maxn 500010
    13 #define INF 1000000000000LL
    14 
    15 int a[20];
    16 
    17 struct node
    18 {
    19     int x,y,next;
    20     LL c;
    21 }t[Maxm];int len=0;
    22 
    23 // vector<int > e[Maxn],c[Maxn];
    24 
    25 int first[Maxn];
    26 
    27 void ins(int x,int y,LL c)
    28 {
    29     t[++len].x=x;t[len].y=y;t[len].c=c;
    30     t[len].next=first[x];first[x]=len;
    31 }
    32 
    33 LL dis[Maxn];
    34 bool inq[Maxn];
    35 queue<int > q;
    36 void spfa()
    37 {
    38     int st=0;
    39     while(!q.empty()) q.pop();
    40     memset(inq,0,sizeof(inq));
    41     // memset(dis,63,sizeof(dis));
    42     for(int i=0;i<a[1];i++) dis[i]=INF;
    43     q.push(st);dis[st]=0;inq[st]=1;
    44     while(!q.empty())
    45     {
    46         int x=q.front();
    47         for(int i=first[x];i;i=t[i].next)
    48         {
    49             int y=t[i].y;
    50         // for(int i=0;i<e[x].size();i++)
    51         // {
    52             // int y=e[x][i];
    53             if(dis[y]>dis[x]+t[i].c)
    54             {
    55                 dis[y]=dis[x]+t[i].c;
    56                 // dis[y]=dis[x]+c[x][i];
    57                 while(!inq[y])
    58                 {
    59                     inq[y]=1;
    60                     q.push(y);
    61                 }
    62             }
    63         }
    64         inq[x]=0;
    65         q.pop();
    66     }
    67 }
    68 
    69 LL get_ans(LL x,LL y)
    70 {
    71     if(x<y) return 0;
    72     return (x-y)/a[1]+1;
    73 }
    74 
    75 int main()
    76 {
    77     int n;
    78     LL L,R;
    79     scanf("%d%lld%lld",&n,&L,&R);
    80     for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    81     sort(a+1,a+1+n);
    82     memset(first,0,sizeof(first));
    83     for(int i=1;i<=n;i++)
    84      for(int j=0;j<a[1];j++)
    85      {
    86          ins(j,(j+a[i])%a[1],a[i]);
    87      }
    88     spfa();
    89     LL ans=0;
    90     for(int i=0;i<a[1];i++) 
    91         ans+=get_ans(R,dis[i])-get_ans(L-1,dis[i]);
    92     printf("%lld
    ",ans);
    93     return 0;
    94 }
    View Code

    WA了很久竟然是spfa打错了。。。

    2017-01-13 19:05:54

  • 相关阅读:
    vue element-ui配置第三方图标库
    HTTP协议:状态码
    HTTP协议:无状态
    CDN:基础知识
    【转载】浅析机器视觉中的照明系统(该如何打光)
    nginx 端口转发
    Gitlab 备份 | 恢复 | 卸载 | 迁移 | 版本升级
    微信小程序支付服务端.net core实现,简单直接
    生产级gitlab备份
    背锅之旅:前任对我的爱-只备份不删除导致的磁盘爆满
  • 原文地址:https://www.cnblogs.com/Konjakmoyu/p/6283832.html
Copyright © 2011-2022 走看看