【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\n",ans);
93     return 0;
94 }

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

2017-01-13 19:05:54

时间: 2024-12-14 10:03:54

【BZOJ 2118】 2118: 墨墨的等式 (最短路)的相关文章

BZOJ 2118: 墨墨的等式

2118: 墨墨的等式 Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 1656  Solved: 650[Submit][Status][Discuss] Description 墨墨突然对等式很感兴趣,他正在研究a1x1+a2y2+…+anxn=B存在非负整数解的条件,他要求你编写一个程序,给定N.{an}.以及B的取值范围,求出有多少B可以使等式存在非负整数解. Input 输入的第一行包含3个正整数,分别表示N.BMin.BMax分别表示数

数论+spfa算法 bzoj 2118 墨墨的等式

2118: 墨墨的等式 Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 1283  Solved: 496 Description 墨墨突然对等式很感兴趣,他正在研究a1x1+a2y2+…+anxn=B存在非负整数解的条件,他要求你编写一个程序,给定N.{an}.以及B的取值范围,求出有多少B可以使等式存在非负整数解. Input 输入的第一行包含3个正整数,分别表示N.BMin.BMax分别表示数列的长度.B的下界.B的上界.输入的第二行包含N个

2118: 墨墨的等式

2118: 墨墨的等式 https://www.lydsy.com/JudgeOnline/problem.php?id=2118 分析: 最短路. 题意就是判断[L,R]内多少数,可以被许多个a1,a2,a3...构成.设最小的Mi = min{ai}. 直接枚举肯定超时,那么换个方法枚举. 考虑一个能构成的数b,它一定可以分解为$b = k \times M_i + r, \ r<M_i$.而且$b + M_i$也是可以构成的.所以我们可以找到最小的%Mi=r的数,比它大的%Mi=r的数可以

bzoj2118 墨墨的等式

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 输出一个

BZOJ2118墨墨的等式[数论 最短路建模]

2118: 墨墨的等式 Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 1317  Solved: 504[Submit][Status][Discuss] Description 墨墨突然对等式很感兴趣,他正在研究a1x1+a2y2+…+anxn=B存在非负整数解的条件,他要求你编写一个程序,给定N.{an}.以及B的取值范围,求出有多少B可以使等式存在非负整数解. Input 输入的第一行包含3个正整数,分别表示N.BMin.BMax分别表示数

BZOJ 2007 海拔(平面图最小割-最短路)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=2007 题意:给出一个n*n的格子,那么顶点显然有(n+1)*(n+1)个.每两个相邻顶点之间有两条边,这两条边是有向的,边上有权值..左上角为源点,右下角为汇点,求s到t的最小割. 思路:很明显这是一个平面图,将其转化为最 短路.我们将s到t之间连一条边,左下角为新图的源点S,右上角区域为新图的终点T,并且为每个格子编号.由于边是有向的,我们就要分析下这条边应该是哪 个点向哪个点的边.

BZOJ 2433 智能车比赛(计算几何+最短路)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=2433 题意:若干个矩形排成一排(同一个x之上最多有一个矩形),矩形i和i+1相邻.给定两点S和T,两点均在矩形内.求S到T的最短路径.只能在矩形内部走. 思路:首先,S到T若有转弯,必定是在矩形 的顶点处转弯.因此,只要建立任意两可达顶点(包含S和T)之间距离求最短路即可.若暴力枚举任意两点再判是否可达复杂度O(n^3).优化.枚举起点 a,从左向右扫遍矩形,利用叉积维护关于该点a的上

BZOJ 2118 墨墨的等式(最短路)

[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2118 [题目大意] 求a1x1+a2y2+…+anxn=B在B的取值范围,有多少B可以使等式存在非负整数解. [题解] 同余最短路,不等式解集计数即可. [代码] #include <cstdio> #include <algorithm> #include <queue> using namespace std; const int N=500010; n

【BZOJ】2118 墨墨的等式

[解析]最短路 [Overview]给定n个物品,每个物品有一个非负价值,问[L,R]区间内有多少价值可以被凑出来. [Analysis] 这道题很多神犇的题解都写得模模糊糊的,貌似看了好久才弄懂,下面是原创啊. 生成函数?TLE. 对于区间[l,r]的答案,可以通过差分转化为 1到r的答案数 - 1到(l-1)的答案数. 注意这道题是求有多少个值能被凑出来,而不是有多少种方法,只要判断一个值行不行就可以了. 选取一个数x=p[rand()%n+1],假设可以凑出值a满足 a mod x=b,0