BZOJ2118: 墨墨的等式
来源:互联网 发布:multisim少数据库 编辑:程序博客网 时间:2024/04/30 02:18
题目大意:
给出一个关于许多x的不定方程:a1*x1+a2*x2+a3*x3+……..+an*xn=B,这里a都是非负整数,求在给定区间[l,r]内,使得所有x都为非负整数的,满足条件的B的个数。
这道怎么看都是数论题的题,其实可以用图论来解决,(额,好像有些突然)。先来分析一下吧,这道题弱机的我肯定是找不到什么优秀的数学方法来解决的,那么我就只好暴力枚举了(反正又不是我算。)直接枚举肯定是要T掉的,怎么办呢?这时我们会想到利用解决大数据、大规模的数学题时所用的方法——余数计算!
余数会满足大多数基本运算性质,还拥有许多优美的性质。枚举整个区间会超时,那么我们来枚举余数呢?恩,这好像是一个好思路。因为B是一个连续的区间,如果一个%a==k的数可以被我们“斗”出来,那么区间内所有%a==k的数都能被“斗”出来。
现在再针对这道题来看看,我们在这些a里任取一个ai,表示为cc,那么这个B%cc肯定是在0~cc-1之间的,如果一个B满足条件%cc==k,那么(B+cc)%cc也肯定==k,那其实就是说,只要我们能找到,%cc==k的,且满足条件的最小的B,在一直往上加cc,直到加到r为止,能有多少个B,(这些B都是符合条件的),就得到了B%cc==k所有的可能,再枚举不同的k,累加起来,就是0~r内全部可能的B值了。同理,0~l-1内所有可能的B值也可以求出,一减就是l~r内的可能了!
然后,为了使不同的余数k种类尽量少,所以ai(cc)尽量小就可以了,取a里面的最小值即可。
那么问题就转化为求%cc==k的B在非负范围之内最小的值是多少。我们不难发现,B==0为非负范围内最小的一个解,那么其他所有余数的最小B都可以从0这里加上若干个数而得到(a非负)。这样有一点最短路的感觉了吗?我们把0看做原点,我们可以在上面加上a1~aN中任意若干个数,相当于选择长度为a1~aN的路径(可重复)向外走,使得它走到一个%cc==k的距离最短。
然后,就可以用dis[k]保存%cc==k时最小的B,初始化dis[0]=0,通过加上不同的ai,得到新的余数,如果得到相同的余数k的话,可以用B较小的来更新dis[k],用spfa解决。
因为是用的stl里的queue,所以不用担心循环队列的问题。还有就是如果哪一个ai==0,对结果并没有影响,不用保存,因为cc是不能为0的。
#include<cstdio>#include<queue>#include<algorithm>using namespace std;typedef long long LL;const int N = 500010;int vis[N], n, a[N], cc;LL dis[N], l, r, inf = 1e9;void spfa(){ queue<int> qu; qu.push(0); vis[0] = 1; dis[0] = 0;//0为其中最小的一个解 while(!qu.empty()){ int u = qu.front(); qu.pop(); vis[u] = 0; for(int i=1; i<=n; i++){ int y = (u + a[i]) % cc; if(dis[y] > dis[u] + a[i]){ dis[y] = dis[u] + a[i]; if(!vis[y]){ qu.push(y); vis[y] = 1; } } } }}LL query(LL lim){//0~lim中B的和 LL ans = 0; for(int i=0; i<cc; i++) if(dis[i] <= lim) ans += (lim - dis[i]) / cc + 1;//因为有两端,所以是上限减下限除以公差加一 return ans;}int main(){ cc = (1 << 30) - 1;//cc用来保存a[1]~a[n]中最小的一个值 scanf("%d%lld%lld", &n, &l, &r); for(int i=1; i<=n; i++){ scanf("%d", &a[i]); if(a[i] == 0){ i--,n--;//如果a==0,对结果毫无影响,直接删去 continue ; } cc = min(cc,a[i]); } for(int i=0; i<cc; i++) dis[i] = 1e18;//要求最短路,初始化为最长 spfa();//dis[i]中存B的解中满足%cc==i最小的一个数 printf("%lld", query(r) - query(l-1)); return 0;}
- [bzoj2118]墨墨的等式
- BZOJ2118 墨墨的等式
- BZOJ2118: 墨墨的等式
- bzoj2118 墨墨的等式
- BZOJ2118: 墨墨的等式
- 【bzoj2118】墨墨的等式
- BZOJ2118: 墨墨的等式
- 【BZOJ2118】墨墨的等式
- bzoj2118 墨墨的等式 最短路
- 【BZOJ2118】墨墨的等式(dijkstra)
- 【bzoj2118】墨墨的等式 最短路建模
- BZOJ2118: 墨墨的等式 思维建图
- [BZOJ2118]墨墨的等式(数学+图论)
- 墨墨的等式
- 【bzoj2257】墨墨的等式
- 2118: 墨墨的等式
- bzoj2118
- 【BZOJ】2118 墨墨的等式
- python3学习笔记:枚举enum
- 【Mac】关于Launchpad空白文件夹问题
- 递推递归练习N
- linux与windows字符编码格式的自动调整
- linux根目录下各文件夹的作用以及tar命令下C,V,Z,F作用
- BZOJ2118: 墨墨的等式
- java-抽象类、接口
- windows下打开.ipynb文件
- lintcode阶梯训练第六关(九章)
- 使用ibus-rime输入法
- Halcon linux makefile 配置
- dfs+链式前向星
- 【Linux】用Yum搭建Shadowsocks服务器
- pod update, LoadError