@ZCDHJ
2019-08-10T00:08:06.000000Z
字数 1581
阅读 852
未分类
给定 的取值范围,求使得 元一次方程 有非负整数解的 的个数。
很明显如果 ,则 加上任意一个 也能使得方程有非负整数解。转化为如 使方程有非负整数解则 也可以。那么对于任意一个 的剩余系来讨论,设 满足 , 可以使得方程有非负整数解且 最小,那么就可以看成是一个最短路模型,求出所有的 ,如果 , 就满足条件。为了使速度最快选择最小的 ,将答案转化为前缀和相减的形式计算即可。为什么这样算出的答案不重不漏呢?因为这里的每个 必然只能构造出 的系数为 的解,然后再用这个数统计 的系数不为 的解,所以不重不漏。
这里放上模板题 Luogu2371 墨墨的等式 的代码
#include <iostream>#include <cstdio>#include <cstring>#include <queue>typedef long long LL;#define int long longconst int MAXN = 20;const int MAXA = 5e5;int n, m, b_max, b_min;int a[MAXN | 1], fst[MAXN | 1], dist[MAXA];struct Queue {int dis, x;Queue() : dis(0), x(0) {}Queue(int a, int b) : x(a), dis(b) {}friend bool operator< (const Queue &lhs, const Queue &rhs) {return lhs.dis > rhs.dis;}};inline int read() {register int x = 0;register char ch = getchar();while (!isdigit(ch)) ch = getchar();while (isdigit(ch)) {x = x * 10 + ch - '0';ch = getchar();}return x;}void Dijkstra() {memset(dist, 0x3f, sizeof(dist));dist[0] = 0;std::priority_queue < Queue > q;q.push(Queue(0, 0));do {Queue from = q.top();q.pop();if (dist[from.x] != from.dis) continue;for (int i = 1; i <= n; ++i) {int to = (from.x + a[i]) % m, w = a[i];if (dist[to] > dist[from.x] + w) {dist[to] = dist[from.x] + w;q.push(Queue(to, dist[to]));}}} while (!q.empty());}LL query(LL x) {LL res = 0;for (int i = 0; i < m; ++i)if (dist[i] <= x)res += (x - dist[i]) / m + 1;return res;}signed main() {freopen("code.in", "r", stdin);freopen("code.out", "w", stdout);n = read();scanf("%lld %lld", &b_min, &b_max);m = 1e9;for (int i = 1; i <= n; ++i) a[i] = read(), m = std::min(m, a[i]);Dijkstra();printf("%lld\n", query(b_max) - query(b_min - 1));return 0;}