bzoj 2118 墨墨的等式
2015-11-16 10:38
162 查看
又是好一道数论题!令mn为a[1]~a
中数的最小值。很显然,如果x能被凑出来,x+mn也能被凑出来。所以我们只需要知道对于每一个x属于[0,mn),满足y%mn==x中最小的y,那么就能知道[1,R]中模mn等于x的数里能凑出来的个数。注意spfa的时候正无穷要大一点需要特殊处理一下a=0的情况,但是数据好像a!=0
中数的最小值。很显然,如果x能被凑出来,x+mn也能被凑出来。所以我们只需要知道对于每一个x属于[0,mn),满足y%mn==x中最小的y,那么就能知道[1,R]中模mn等于x的数里能凑出来的个数。注意spfa的时候正无穷要大一点需要特殊处理一下a=0的情况,但是数据好像a!=0
#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 ; ll dis ; bool vis ; int mn,n; int a[20]; void spfa() { int h=0,w=1,x,y; q[1]=0; vis[0]=1; while (h!=w) { h++; if (h>mn+5) h=1; x=q[h]; for (int i=1;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]=1; w++; if (w>mn+5) w=1; q[w]=y; } } } vis[x]=0; } } ll query(ll x) { ll ans=0; for (int i=0;i<mn;i++) if (dis[i]<=x) ans+=(x-dis[i])/mn+1; return ans; } int main() { mn=(1e9); ll L,R; scanf("%d%lld%lld",&n,&L,&R); for (int i=1;i<=n;i++) { scanf("%d",&a[i]); if (a[i]==0) { i--; n--; continue;} mn=min(mn,a[i]);} for (int i=1;i<mn;i++) dis[i]=inf; spfa(); printf("%lld\n",query(R)-query(L-1)); return 0; }
相关文章推荐
- <android5.0>之曲线动画(Curved motion(曲线运动))
- 浅谈虚数i在电路分析中的作用
- 【数据库7】字段相关与联合结果集
- Jenkins入门系列之——02第二章 Jenkins安装与配置
- 简述类目的优缺点,如果覆盖了本类或者父类的方法 ,会出现什么问题
- [Hibernate系列—] 1. 下载与试用Hibernate(MySQL与Oracle 配置)
- Java中String转化为其他类型方法汇总
- 用R做线性回归
- 出圈问题
- Jenkins入门系列之——01第一章 Jenkins是什么?
- bzoj 4010 菜肴制作|拓扑排序|priority_queue|解题思想
- bzoj 1414 对称的正方形
- 网络流刷题列表
- bzoj 2084 反对称子串
- bzoj 3790 神奇项链
- bzoj 3631 松鼠的新家
- bzoj 1064 假面舞会
- bzoj 3240 矩阵游戏
- bzoj 2435 道路修建
- bzoj 1562 变换序列