建图最短路同余(luogu2662 vijos1054 xjoi2157)(bzoj2118)
来源:互联网 发布:mix2 知乎 编辑:程序博客网 时间:2024/06/05 14:34
John计划为他的牛场建一个围栏,以限制奶牛们的活动。他有N种可以建造围栏的木料,长度分别是l1,l2…lN,每种长度的木料无限。修建时,他将把所有选中的木料拼接在一起,因此围栏的长度就是他使用的木料长度之和。但是聪明的John很快发现很多长度都是不能由这些木料长度相加得到的,于是决定在必要的时候把这些木料砍掉一部分以后再使用。不过由于John比较节约,他给自己规定:任何一根木料最多只能削短M米。当然,每根木料削去的木料长度不需要都一样。不过由于测量工具太原始,John只能准确的削去整数米的木料,因此,如果他有两种长度分别是7和11的木料,每根最多只能砍掉1米,那么实际上就有4种可以使用的木料长度,分别是6, 7, 10, 11。
Clevow是John的牛场中的最聪明的奶牛,John请她来设计围栏。Clevow不愿意自己和同伴在游戏时受到围栏的限制,于是想刁难一下John,希望John的木料无论经过怎样的加工,长度之和都不可能得到她设计的围栏总长度。
不过Clevow知道,如果围栏的长度太小,John很快就能发现它是不能修建好的。因此她希望得到你的帮助,找出无法修建的最大围栏长度。
格式
输入格式
输入的第一行包含两个整数N, M (1<N<100, 0<=M<3000),分别表示木料的种类和每根木料削去的最大值。以下各行每行一个整数li(1<li<3000),表示第i根木料的原始长度。
输出格式
输出仅一行,包含一个整数,表示不能修建的最大围栏长度。如果任何长度的围栏都可以修建或者这个最大值不存在,输出-1。
样例1
样例输入1
2 17 11
样例输出1
15
对问题进行转换
在modl[1]的剩余系下,我们设dis[i]表示i=modl[1]的最小的体积
那么如果dis[i]可以到达, 那么dis[i]+l[1]*k(k=0~无限大)都是可以到达的。
初始的时候dis[0]=0,因为l[1]%l[1]=0,并且如果等于l[1]的话后面的点一定要对其进行松弛而实际上不需要。
于是我们通过mod对每一个点进行松弛,
答案就是根据定义的最小体积减去l[1],因为modl[1]
判断无解的情况
1.最小的是1, 那么所有的点都可以以1进行松弛,那么所有的点都可以到达。
2.有一个余数不能到达,那么他的 dis[i]+l[1]*k(k=0~无限大)也都是不能到达的。
于是我们在求最短路的时间复杂度内解决了这个问题
spfa o(n^2) dij(nlgn)
#include<bits/stdc++.h>using namespace std;int dis[30000],book[30000],l[30000],n,m,ans,a[30000],vis[30000],cnt=0;int spfa(){memset(book,0,sizeof(book));memset(dis,36,sizeof(dis));int inf=dis[1];dis[0]=0;book[0]=1;queue<int> q;q.push(0);while(!q.empty()){int x=q.front();q.pop();book[x]=0;for(int i=2;i<=cnt;i++){if(dis[x]+l[i]<dis[(x+l[i])%l[1]]){dis[(x+l[i])%l[1]]=dis[x]+l[i];if(!book[(x+l[i])%l[1]])book[(x+l[i])%l[1]]=1,q.push((x+l[i])%l[1]);}}}for(int i=0;i<l[1];i++)if(dis[i]==inf) return -1;int ans=0;for(int i=0;i<l[1];i++) ans=max(ans,dis[i]-l[1]);return ans;}main(){scanf("%d%d",&n,&m);for(int i=1;i<=n;i++){scanf("%d",&a[i]);for(int j=a[i]-m;j<=a[i];j++)if(j>=1) vis[j]=1;}if(vis[1]){cout<<"-1\n";return 0;}for(int i=1;i<=3000;i++)if(vis[i])l[++cnt]=i; printf("%d",spfa());return 0;}
第二种写法和第一种思路是一样的,但是第二种的dis数组表示的是l[1]*dis[i]+i
#include<bits/stdc++.h>using namespace std;int dis[30000],book[30000],l[30000],n,m,ans,a[30000],vis[30000],cnt=0; int spfa(){ memset(book,0,sizeof(book));memset(dis,36,sizeof(dis)); int inf=dis[1];dis[0]=0;book[0]=1; queue<int> q;q.push(0); while(!q.empty()) { int x=q.front();q.pop();book[x]=0; for(int i=2;i<=cnt;i++) { if(dis[x]+(x+l[i])/l[1]<dis[(x+l[i])%l[1]]) { dis[(x+l[i])%l[1]]=dis[x]+(x+l[i])/l[1]; if(!book[(x+l[i])%l[1]]) book[(x+l[i])%l[1]]=1,q.push((x+l[i])%l[1]); } } } for(int i=0;i<l[1];i++) if(dis[i]==inf) return -1; int ans=0; for(int i=0;i<l[1];i++) ans=max(ans,dis[i]*l[1]+i); return ans-l[1];} main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { scanf("%d",&a[i]); for(int j=a[i]-m;j<=a[i];j++)if(j>=1) vis[j]=1; } if(vis[1]){cout<<"-1\n";return 0;} for(int i=1;i<=3000;i++)if(vis[i])l[++cnt]=i; printf("%d",spfa()); return 0;}
再放一题一样的。
2118: 墨墨的等式
Time Limit: 10 Sec Memory Limit: 259 MBSubmit: 1905 Solved: 754
[Submit][Status][Discuss]
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。
#include<bits/stdc++.h>#define int long longusing namespace std;int dis[500000],book[500000],l[500000],n,m,ans,vis[500000],cnt=0,ll,rr;int calc(int x){int ans=0;for(int i=0;i<l[1];i++)ans+=max(0ll,x/l[1]+((x%l[1])>=i)-dis[i]);return ans;} int spfa(){memset(book,0,sizeof(book));memset(dis,36,sizeof(dis));int inf=dis[1];dis[0]=0;book[0]=1;queue<int> q;q.push(0);while(!q.empty()){int x=q.front();q.pop();book[x]=0;for(int i=2;i<=n;i++) { if(dis[x]+(x+l[i])/l[1]<dis[(x+l[i])%l[1]]) { dis[(x+l[i])%l[1]]=dis[x]+(x+l[i])/l[1]; if(!book[(x+l[i])%l[1]]) book[(x+l[i])%l[1]]=1,q.push((x+l[i])%l[1]); } }}}main(){scanf("%lld%lld%lld",&n,&ll,&rr);for(int i=1;i<=n;i++)scanf("%lld",&l[i]);sort(l+1,l+n+1); if(l[n]==0){cout<<"0\n";return 0;}spfa();printf("%lld",calc(rr)-calc(ll-1));return 0;}
- 建图最短路同余(luogu2662 vijos1054 xjoi2157)(bzoj2118)
- HDU6071Lazy Running(同余最短路)
- luogu2662 牛场围栏(数论+最短路)
- HDU 6071 Lazy Running(同余+最短路)
- HDU 6071 Lazy Running(同余最短路)
- HDU 6071 Lazy Running(模同余最短路)
- 同余最短路
- 同余最短路
- 同余问题(3)一元线性同余方程组
- 2017年多校赛第四场 1005 Lazy Running(同余最短路)
- POJ 3844(同余)
- 数论(同余+hash)
- Light1078(同余定理)
- 2016 (同余定理)
- CSU1803 2016(同余)
- 同余方程(扩欧)
- 同余+最短路 做完全背包
- POI X Sums(同余最短路)
- 数论学习(题库有很多啦。)
- 51nod 1242 斐波那契数列第N项
- 树链剖分基础模板(BZOJ1036[ZJOI2008]树的统计Count)
- 树链剖分模板题(luogu3384 【模板】树链剖分)
- Java源码阅读之ArrayList
- 建图最短路同余(luogu2662 vijos1054 xjoi2157)(bzoj2118)
- 左偏树
- 欧拉函数性质证明 : n所有约数的欧拉函数和等于n
- 冒泡排序法(Bubble Sorting)
- contest 15
- 为什么要来写博客
- 计算几何基础模板 以后还会更新
- 判断直线相交思维好题 (poj1039)
- 莫比乌斯反演学习之路~