2118: 墨墨的等式
Time Limit: 10 Sec Memory Limit: 259 MBSubmit: 2271 Solved: 893
[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
2 5 10
3 5
3 5
Sample Output
5
HINT
对于100%的数据,N≤12,0≤ai≤5*10^5,1≤BMin≤BMax≤10^12。
Source
一波骚操作图论建模加最短路,原理很玄妙啊。鄙人不才(其实是懒(~ ̄▽ ̄)~ ),这篇博客就讲的比较清楚 我是“这篇博客”
#include<cstdio>
#include<cstring>
#include<queue>
#define For(i, a, b) for(register int i = a; i <= b; ++i)
using namespace std;
const int maxn = 5e5 + 5;
const int inf = 0x3f3f3f3f;
struct edge {
int v, w, next;
}e[maxn * 13];
int head[maxn], cnt, n, a[15], ax, vis[maxn];
long long dis[maxn], ans, D, U;
void adde(const int & u, const int & v, const int & w) {
e[cnt] = (edge){v, w, head[u]};
head[u] = cnt++;
}
void SPFA() {
memset(dis, inf, sizeof(dis));
deque<int > q;
q.push_back(0);
dis[0] = 0;
while(!q.empty()) {
int u = q.front();
q.pop_front(), vis[u] = 0;
for(register int i = head[u]; ~i; i = e[i].next) {
if(dis[u] + e[i].w <= dis[e[i].v]) {
dis[e[i].v] = dis[u] + e[i].w;
if(vis[e[i].v]) continue;
if(!q.empty() && dis[e[i].v] <= dis[q.front()]) q.push_front(e[i].v);
else q.push_back(e[i].v);
vis[e[i].v] = 1;
}
}
}
}
int main() {
memset(head, -1, sizeof(head));
scanf("%d%lld%lld", &n, &D, &U);
ax = inf;
For(i, 1, n) scanf("%d", &a[i]), ax = min(ax, a[i]);
For(i, 0, ax - 1)
For(j, 1, n) adde(i, (i + a[j]) % ax, a[j]);
SPFA();
--D;
For(i, 0, ax - 1) {
if(dis[i] <= U) ans += (U - dis[i])/ax + 1;
if(dis[i] <= D) ans -= (D - dis[i])/ax + 1;
}
printf("%lld", ans);
return 0;
}
rockdu
没有帐号? 立即注册