2118: 墨墨的等式

Time Limit: 10 Sec  Memory Limit: 259 MB
Submit: 1283  Solved: 496

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。

/*
一开始就没想到是个最短路。
题目可以这样变化一下:n个物品,可以用0-,正无穷,问[l,r]区间内有多少价值可以凑出来。
联系到最短路上面:
任选一个ai>0,如果一个价值k∗ai+x(0≤x<ai,k≥0)可以被凑出来,那么显然(k+1)∗ai+x,(k+2)∗ai+x,...都可以被凑出来(这样x的范围就是小于ai了)
显然如果我们对于每个x都找到最小的k满足k∗ai+x可以被凑出来,这个问题就解决了,如果满足凑出x的最小花费是大于b的,那么就不能在[l,r]区间内凑出mn*k+x,这个数了,否则的话,就计算[l,r]内有多少个可以凑出来。
最短路,spfa
时间复杂度O(n∗ai∗log2ai)
因为复杂度与ai有关,所以我们就选择最小的ai了,举个例子:当最小的ai等于1时,那么自然区间内的所有数都可以凑出来了。
*/
 /*网上的AC代码,我加了注解,注意把I64d改为lld*/
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath> #define md
#define ll long long
#define inf 1000000000000000LL
#define eps 1e-8
#define N 500010
using namespace std;
int q[N];
ll dis[N];
bool vis[N];
int mn,n;
int a[];
void spfa()
{
int h=,w=,x,y; q[]=; vis[]=;/*第一个能凑出的数就是0*/
while (h!=w)
{
h++; if (h>mn+) h=; x=q[h];/*循环队列,取出队头的数*/
for (int i=;i<=n;i++)
{
y=(x+a[i])%mn;/*利用这个价值和其他价值组合所能达到的y,计算y的最小花费(因为只有计算最小花费),才能用mn凑出更多的满足区间条件的数*/
if (dis[y]>dis[x]+a[i])
{
dis[y]=dis[x]+a[i];
if (!vis[y])
{
vis[y]=;
w++; if (w>mn+) w=; q[w]=y;
}
}
}
vis[x]=;
}
} ll query(ll x)
{
ll ans=;
for (int i=;i<mn;i++)
if (dis[i]<=x) ans+=(x-dis[i])/mn+; /*计算有多少个k满足k*mn+i<=x,因为k>=0,所以还要加1*/
return ans;
} /*windows 用I64d linux 用lld*/
int main()
{
mn=(1e9);
ll L,R;
scanf("%d%I64d%I64d",&n,&L,&R);
for (int i=;i<=n;i++) { scanf("%d",&a[i]); if (a[i]==) { i--; n--; continue;} mn=min(mn,a[i]);}/*取出最小的an,但是不能为0,很好理解吧*/
for (int i=;i<mn;i++) dis[i]=inf;/*设达到每个k*mn+i(i<mn)的最小花费,所以数组dis中只有小于mn的i即可(*/
spfa();
printf("%I64d\n",query(R)-query(L-));
return ;
}
 /*
首先,答案=ans(Bmax)-ans(Bmin-1)//利用差分
找出a1到an中的最小值p,则如果可以构造出答案x,就可以构造出答案x+p
所以我们只需要对于每个q(0<=q<p),计算出最小的k,使k*p+q能够能够被构造出来,那么对于k’(k’>k) k’*p+q也能构造出来
所以对于每个q建一个点,对于每个ai,从q向(q+ai)%p连一条长度为ai的边,先跑一遍最短路,计算出得到每个q的最小花费,如果最小花费大于了Bmax,那么没有办法凑出了。否则就计算可以凑出多少个。 */
#define N 15
#define S 500010 //注意题目时5*1e5
#include<iostream>
using namespace std;
#include<cstdio>
#include<queue>
typedef long long ll;
ll L,R;
bool vis[S]={};
int n,mn=(<<)-,a[N];
ll dis[S];
void input()
{
cin>>n>>L>>R;
for(int i=;i<=n;++i)
{
scanf("%d",&a[i]);
if(a[i]==)
{
i--;n--;
continue;
}
mn=min(mn,a[i]);
}
}
void spfa()
{
queue<int>Q;
Q.push();
vis[]=true;
dis[]=;/*注意得到0的花费是0*/
int x,y;
while(!Q.empty())
{
x=Q.front();Q.pop();
vis[x]=false;
for(int i=;i<=n;++i)
{
y=(x+a[i])%mn;
if(dis[y]>dis[x]+a[i])
{
dis[y]=dis[x]+a[i];
if(!vis[y])
{
vis[y]=true;
Q.push(y);
}
}
}
}
}
ll query(ll x)
{
ll ans=;
for(int i=;i<mn;++i)/*别忘了从0开始循环,因为凑出的是0,可以全部用mn来凑*/
if(dis[i]<=x) ans+=(x-dis[i])/mn+;
return ans;
}
int main()
{
input();
for(int i=;i<mn;++i)
dis[i]=100000000000000000LL;//当赋值longlong的数时,要加后缀ll(大小写都可以)才可以,否则会出错的。
spfa();
cout<<query(R)-query(L-);
return ;
}

数论+spfa算法 bzoj 2118 墨墨的等式的更多相关文章

  1. 【BZOJ 2118】 墨墨的等式(Dijkstra)

    BZOJ2118 墨墨的等式 题链:http://www.lydsy.com/JudgeOnline/problem.php?id=2118 Description 墨墨突然对等式很感兴趣,他正在研究 ...

  2. 【BZOJ 2118】墨墨的等式

    http://www.lydsy.com/JudgeOnline/problem.php?id=2118 最短路就是为了找到最小的$x$满足$x=k×a_{min}+d,0≤d<a_{min}$ ...

  3. bzoj 2118: 墨墨的等式 spfa

    题目: 墨墨突然对等式很感兴趣,他正在研究\(a_1x_1+a_2y_2+ ... +a_nx_n=B\)存在非负整数解的条件,他要求你编写一个程序,给定\(N,\{a_n\}\)以及\(B\)的取值 ...

  4. bzoj 2118 墨墨的等式 - 图论最短路建模

    墨墨突然对等式很感兴趣,他正在研究a1x1+a2y2+…+anxn=B存在非负整数解的条件,他要求你编写一个程序,给定N.{an}.以及B的取值范围,求出有多少B可以使等式存在非负整数解. Input ...

  5. 【BZOJ 2118】 2118: 墨墨的等式 (最短路)

    2118: 墨墨的等式 Description 墨墨突然对等式很感兴趣,他正在研究a1x1+a2y2+…+anxn=B存在非负整数解的条件,他要求你编写一个程序,给定N.{an}.以及B的取值范围,求 ...

  6. bzoj 2118: 墨墨的等式

    Description 墨墨突然对等式很感兴趣,他正在研究a1x1+a2y2+-+anxn=B存在非负整数解的条件,他要求你编写一个程序,给定N.{an}.以及B的取值范围,求出有多少B可以使等式存在 ...

  7. [图论训练]BZOJ 2118: 墨墨的等式 【最短路】

    Description 墨墨突然对等式很感兴趣,他正在研究a1x1+a2y2+…+anxn=B存在非负整数解的条件,他要求你编写一个程序,给定N.{an}.以及B的取值范围,求出有多少B可以使等式存在 ...

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

    2118: 墨墨的等式 Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 1317  Solved: 504[Submit][Status][Discus ...

  9. BZOJ2118: 墨墨的等式(最短路 数论)

    题意 墨墨突然对等式很感兴趣,他正在研究a1x1+a2y2+…+anxn=B存在非负整数解的条件,他要求你编写一个程序,给定N.{an}.以及B的取值范围,求出有多少B可以使等式存在非负整数解. So ...

随机推荐

  1. sql 两列相加存到另一列

    假设表table1有a.b两个列,想生成另一个列为a列值+b列值计算列添加语句如下ALTER TABLE table1ADD c AS a+b

  2. [PHP] 读取大文件并显示

    使用PHP读取日志文件,当文件比较大的时候,会报内存不足,因此应该部分读取,读取指定的行数的数据 PHP代码: <?php class Test{ //日志路径 const LOG_PATH=& ...

  3. ANSI X9.19 MAC算法

    /// <summary> /// 获取MAC校验字节数据 /// </summary> /// <param name="bankData"> ...

  4. velocity merge作为工具类从web上下文和jar加载模板的两种常见情形

    很多时候,处于各种便利性或折衷或者通用性亦或是限制的原因,会借助于模板生成结果,在此介绍两种使用velocity merge的情形,第一种是和spring mvc一样,将模板放在velocityCon ...

  5. mongodb driver c#语法

    Definitions and BuildersThe driver has introduced a number of types related to the specification of ...

  6. “Stamping” PDF Files Downloaded from SharePoint 2010

    http://blog.falchionconsulting.com/index.php/2012/03/stamping-pdf-files-downloaded-from-sharepoint-2 ...

  7. Force.com微信开发系列(六)客服接口

    当用户主动发消息给微信公众账号的时候(包括发送信息.点击自定义菜单click事件.订阅事件.扫描二维码事件.支付成功事件.用户维权),微信将会把消息数据推送给开发者,开发者在一段时间内(目前为48小时 ...

  8. R语言学习笔记:SQL操作

    虽然R很强大,但如果对SQL非常熟悉,也不能浪费这项技能了,可以用上sqldf包,从example("sqldf")抄了几条用法放在这里,以后可能会用上. library(&quo ...

  9. Android项目实战(十一):moveTaskToBack(boolean ) 方法的使用

    当你开发的程序被按后退键退出的时候, 你肯定不想让他就这么被finish()吧,那么就想把程序退置到后台就可. (类似于PC端,你关闭一个浏览器和你最小化一个浏览器的区别) 参看方法:public b ...

  10. iOS设计模式之中介者模式

    中介者模式 基本理解 中介者模式又叫做调停者模式,其实就是中间人或者调停者的意思. 尽管将一个系统分割成许多对象通常可以增加可复用性,但是对象之间的连接又降低了可复用性. 如果两个类不必彼此直接通信, ...