[关闭]
@ZCDHJ 2019-08-10T00:08:06.000000Z 字数 1581 阅读 1092

同余类最短路 笔记

未分类


给定 的取值范围,求使得 元一次方程 有非负整数解的 的个数。

很明显如果 ,则 加上任意一个 也能使得方程有非负整数解。转化为如 任意一个任意个 使方程有非负整数解则 也可以。那么对于任意一个 的剩余系来讨论,设 满足 , 可以使得方程有非负整数解且 最小,那么就可以看成是一个最短路模型,求出所有的 ,如果 , 就满足条件。为了使速度最快选择最小的 ,将答案转化为前缀和相减的形式计算即可。为什么这样算出的答案不重不漏呢?因为这里的每个 必然只能构造出 的系数为 的解,然后再用这个数统计 的系数不为 的解,所以不重不漏。

这里放上模板题 Luogu2371 墨墨的等式 的代码

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstring>
  4. #include <queue>
  5. typedef long long LL;
  6. #define int long long
  7. const int MAXN = 20;
  8. const int MAXA = 5e5;
  9. int n, m, b_max, b_min;
  10. int a[MAXN | 1], fst[MAXN | 1], dist[MAXA];
  11. struct Queue {
  12. int dis, x;
  13. Queue() : dis(0), x(0) {}
  14. Queue(int a, int b) : x(a), dis(b) {}
  15. friend bool operator< (const Queue &lhs, const Queue &rhs) {
  16. return lhs.dis > rhs.dis;
  17. }
  18. };
  19. inline int read() {
  20. register int x = 0;
  21. register char ch = getchar();
  22. while (!isdigit(ch)) ch = getchar();
  23. while (isdigit(ch)) {
  24. x = x * 10 + ch - '0';
  25. ch = getchar();
  26. }
  27. return x;
  28. }
  29. void Dijkstra() {
  30. memset(dist, 0x3f, sizeof(dist));
  31. dist[0] = 0;
  32. std::priority_queue < Queue > q;
  33. q.push(Queue(0, 0));
  34. do {
  35. Queue from = q.top();
  36. q.pop();
  37. if (dist[from.x] != from.dis) continue;
  38. for (int i = 1; i <= n; ++i) {
  39. int to = (from.x + a[i]) % m, w = a[i];
  40. if (dist[to] > dist[from.x] + w) {
  41. dist[to] = dist[from.x] + w;
  42. q.push(Queue(to, dist[to]));
  43. }
  44. }
  45. } while (!q.empty());
  46. }
  47. LL query(LL x) {
  48. LL res = 0;
  49. for (int i = 0; i < m; ++i)
  50. if (dist[i] <= x)
  51. res += (x - dist[i]) / m + 1;
  52. return res;
  53. }
  54. signed main() {
  55. freopen("code.in", "r", stdin);
  56. freopen("code.out", "w", stdout);
  57. n = read();
  58. scanf("%lld %lld", &b_min, &b_max);
  59. m = 1e9;
  60. for (int i = 1; i <= n; ++i) a[i] = read(), m = std::min(m, a[i]);
  61. Dijkstra();
  62. printf("%lld\n", query(b_max) - query(b_min - 1));
  63. return 0;
  64. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注