数论+spfa算法 bzoj 2118 墨墨的等式
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
3 5
Sample Output
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 墨墨的等式的更多相关文章
- 【BZOJ 2118】 墨墨的等式(Dijkstra)
BZOJ2118 墨墨的等式 题链:http://www.lydsy.com/JudgeOnline/problem.php?id=2118 Description 墨墨突然对等式很感兴趣,他正在研究 ...
- 【BZOJ 2118】墨墨的等式
http://www.lydsy.com/JudgeOnline/problem.php?id=2118 最短路就是为了找到最小的$x$满足$x=k×a_{min}+d,0≤d<a_{min}$ ...
- bzoj 2118: 墨墨的等式 spfa
题目: 墨墨突然对等式很感兴趣,他正在研究\(a_1x_1+a_2y_2+ ... +a_nx_n=B\)存在非负整数解的条件,他要求你编写一个程序,给定\(N,\{a_n\}\)以及\(B\)的取值 ...
- bzoj 2118 墨墨的等式 - 图论最短路建模
墨墨突然对等式很感兴趣,他正在研究a1x1+a2y2+…+anxn=B存在非负整数解的条件,他要求你编写一个程序,给定N.{an}.以及B的取值范围,求出有多少B可以使等式存在非负整数解. Input ...
- 【BZOJ 2118】 2118: 墨墨的等式 (最短路)
2118: 墨墨的等式 Description 墨墨突然对等式很感兴趣,他正在研究a1x1+a2y2+…+anxn=B存在非负整数解的条件,他要求你编写一个程序,给定N.{an}.以及B的取值范围,求 ...
- bzoj 2118: 墨墨的等式
Description 墨墨突然对等式很感兴趣,他正在研究a1x1+a2y2+-+anxn=B存在非负整数解的条件,他要求你编写一个程序,给定N.{an}.以及B的取值范围,求出有多少B可以使等式存在 ...
- [图论训练]BZOJ 2118: 墨墨的等式 【最短路】
Description 墨墨突然对等式很感兴趣,他正在研究a1x1+a2y2+…+anxn=B存在非负整数解的条件,他要求你编写一个程序,给定N.{an}.以及B的取值范围,求出有多少B可以使等式存在 ...
- BZOJ2118墨墨的等式[数论 最短路建模]
2118: 墨墨的等式 Time Limit: 10 Sec Memory Limit: 259 MBSubmit: 1317 Solved: 504[Submit][Status][Discus ...
- BZOJ2118: 墨墨的等式(最短路 数论)
题意 墨墨突然对等式很感兴趣,他正在研究a1x1+a2y2+…+anxn=B存在非负整数解的条件,他要求你编写一个程序,给定N.{an}.以及B的取值范围,求出有多少B可以使等式存在非负整数解. So ...
随机推荐
- mysql并发insert deadlock分析以及解决,无delete/update/for update
关于并发insert操作发生deadlock这个情况,一直有很多争议,而且网上的帖子所有的例证和模拟其实不一定反映了真实的情况,例如:https://www.percona.com/blog/2012 ...
- 生理周期(c++实现)
描述:人生来就有三个生理周期,分别为体力.感情和智力周期,它们的周期长度为23 天. 28 天和33 天.每一个周期中有一天是高峰.在高峰这天,人会在相应的方面表现出色.例如,智力周期的高峰,人会思维 ...
- Vue混合
gitHub地址: https://github.com/lily1010/vue_learn/tree/master/lesson13 一 定位 混合以一种灵活的方式为组件提供分布复用功能.混合对象 ...
- 使用Reflexil修改类库
因为公司一个项目需要修改PPS的颜色,于是反编译了PPS的代码发现,作者很不厚道的把所有着色都HardCode在代码里 private static void InsertDefaultSeriesC ...
- 转:【前端福利】用grunt搭建自动化的web前端开发环境-完整教程
原文地址:http://blog.csdn.net/wangfupeng1988/article/details/46418203 jQuery在使用grunt,bootstrap在使用grunt,百 ...
- SqlServer int型转varchar型 出现*号
今天调一个bug,错误提示执行语句 * 附近有语法错误,看了存储过程半天没啥反应,我就更本没有* .打印了一下语句发现 where Mor_Id=* 仔细一看set @sqlupdate+=' whe ...
- iOS之UI--涂鸦画板实例 (有待更新)
首先是搭建框架 其他的略过,直接展示效果: 然后接下来上传搭建好两个控制器框架的源码百度云下载链接: http://pan.baidu.com/s/1skjpDox 密码: ardx ,工程里面还有我 ...
- 解决win2003/2008下注册机或破解补丁程序无法运行问题
win Server 2003/2008 64位系统均遇到注册机或破解补丁程序无法运行或报错或死机的情况,原因是win系统默认开启了文件数据执行保护导致的. (比如3DMax的破解补丁程序等...) ...
- Java 读取指定目录下的文件名和目录名
需求:读取指定目录下的文件名和目录名 实现如下: package com.test.common.util; import java.io.File; public class ReadFile { ...
- tair源码分析——leveldb存储引擎使用
分析完leveldb以后,接下来的时间准备队tair的源码进行阅读和分析.我们刚刚分析完了leveldb而在tair中leveldb是其几大存储引擎之一,所以我们这里首先从tair对leveldb的使 ...