https://www.cnblogs.com/31415926535x/p/11692422.html

一种没见过的处理模型,,记录一下,,主要是用来处理一个多元一次方程的解的数量的问题,,数据量小时可以用看成背包处理,,数据很大时可以转换成最短路模型+一点数学来处理,,(体积模域下的最短路的问题,,求的一个最简的表示形式有模数来得到所有解

墨墨的等式

题目

因为只是求满足的解的数量,,所以可以将方程转换成一个模方程组,,这样的方程组的解显然也是原来的解的子集,,同时可以利用模数来得到所有解,,

模数的选择是最小的那个系数,,因为如果任意选择,,会出现一些多考虑的情况

弄 mi 个点,表示从0到mi-1的所有数,,建边的方法是 i->(i+a[j])%mi 边权为 a[j] ,,表示从i这个点变成后面一个数的费用,,(因为两边都是取模的,,所以每一个数取几次后的和的余数就是那些经过的点,,也就是说一条路径就是得到一个右边为 i(mod mi) 的一个最小解,,这个最小的解就是费用和,,也就是一条最短路dis[i]

这样我们对于每一个取模的右边的B都计算一下区间里的数量,,,(计算这玩意推错了一次,,emmm

参考

  1. #include <bits/stdc++.h>
  2. #define aaa cout<<233<<endl;
  3. #define endl '\n'
  4. using namespace std;
  5. typedef long long ll;
  6. typedef unsigned long long ull;
  7. typedef long double ld;
  8. // mt19937 rnd(TM(0));
  9. const int inf = 0x3f3f3f3f;//1061109567 > 1e9
  10. const ll linf = 0x3f3f3f3f3f3f3f3f;
  11. const double eps = 1e-6;
  12. const double pi = 3.14159265358979;
  13. const int maxn = 3e6 + 5;
  14. const int maxm = 1e7 + 233;
  15. const int mod = 1e9 + 7;
  16. ll n, l, r, a[maxn];
  17. struct edge
  18. {
  19. int to, nxt; ll w;
  20. }edge[maxn << 1];
  21. int tot, head[maxn << 1];
  22. void init()
  23. {
  24. tot = 0;
  25. memset(head, -1, sizeof head);
  26. }
  27. void addedge(int u, int v, ll w)
  28. {
  29. edge[tot].to = v;
  30. edge[tot].w = w;
  31. edge[tot].nxt = head[u];
  32. head[u] = tot++;
  33. }
  34. struct node
  35. {
  36. int v; ll w;
  37. node(){}
  38. node(int _v, ll _w):v(_v), w(_w){}
  39. const bool operator<(const node &r)const{
  40. return w > r.w;
  41. }
  42. }tmp;
  43. ll dis[maxn];
  44. bool vis[maxn];
  45. void dijkstra(int s)
  46. {
  47. memset(dis, inf, sizeof dis);
  48. memset(vis, false, sizeof vis);
  49. priority_queue<node> q;
  50. while(!q.empty())q.pop();
  51. q.push(node(s, 0));
  52. dis[s] = 0;
  53. while(!q.empty())
  54. {
  55. tmp = q.top(); q.pop();
  56. if(vis[tmp.v])continue;
  57. vis[tmp.v] = true;
  58. for(int i = head[tmp.v]; ~i; i = edge[i].nxt)
  59. {
  60. int v = edge[i].to;
  61. if(dis[v] > dis[tmp.v] + edge[i].w)
  62. {
  63. dis[v] = dis[tmp.v] + edge[i].w;
  64. q.push(node(v, dis[v]));
  65. }
  66. }
  67. }
  68. }
  69. int main()
  70. {
  71. // double pp = clock();
  72. // freopen("233.in", "r", stdin);
  73. // freopen("233.out", "w", stdout);
  74. ios_base::sync_with_stdio(0);
  75. cin.tie(0);cout.tie(0);
  76. cin >> n >> l >> r;
  77. for(int i = 1; i <= n; ++i)cin >> a[i];
  78. sort(a + 1, a + 1 + n);
  79. int mi = a[1];
  80. init();
  81. for(int i = 0; i <= mi - 1; ++i)
  82. for(int j = 1; j <= n; ++j)
  83. addedge(i, (i + a[j]) % mi, a[j]);
  84. dijkstra(0);
  85. ll ans = 0;
  86. for(int i = 0; i <= mi - 1; ++i)
  87. {
  88. if(dis[i] <= r)
  89. {
  90. if(dis[i] == 0)dis[i] = mi;
  91. ans += (r - dis[i]) / mi + 1;
  92. if(l > dis[i])ans -= (l - dis[i] - 1) / mi + 1;
  93. }
  94. }
  95. cout << ans << endl;
  96. return 0;
  97. }

P3403 跳楼机

题目

比上面那个简单些,,就是注意细节,,从1开始,,有一个是1那么值一定是h,,,

  1. #include <bits/stdc++.h>
  2. #define aaa cout<<233<<endl;
  3. #define endl '\n'
  4. using namespace std;
  5. typedef long long ll;
  6. typedef unsigned long long ull;
  7. typedef long double ld;
  8. // mt19937 rnd(TM(0));
  9. const int inf = 0x3f3f3f3f;//1061109567 > 1e9
  10. const ll linf = 0x3f3f3f3f3f3f3f3f;
  11. const double eps = 1e-6;
  12. const double pi = 3.14159265358979;
  13. const int maxn = 3e6 + 5;
  14. const int maxm = 1e7 + 233;
  15. const int mod = 1e9 + 7;
  16. ll n, l, r, a[maxn];
  17. struct edge
  18. {
  19. int to, nxt; ll w;
  20. }edge[maxn << 1];
  21. int tot, head[maxn << 1];
  22. void init()
  23. {
  24. tot = 0;
  25. memset(head, -1, sizeof head);
  26. }
  27. void addedge(int u, int v, ll w)
  28. {
  29. edge[tot].to = v;
  30. edge[tot].w = w;
  31. edge[tot].nxt = head[u];
  32. head[u] = tot++;
  33. }
  34. struct node
  35. {
  36. int v; ll w;
  37. node(){}
  38. node(int _v, ll _w):v(_v), w(_w){}
  39. const bool operator<(const node &r)const{
  40. return w > r.w;
  41. }
  42. }tmp;
  43. ll dis[maxn];
  44. bool vis[maxn];
  45. void dijkstra(int s)
  46. {
  47. memset(dis, inf, sizeof dis);
  48. memset(vis, false, sizeof vis);
  49. priority_queue<node> q;
  50. while(!q.empty())q.pop();
  51. q.push(node(s, 0));
  52. dis[s] = 1;
  53. while(!q.empty())
  54. {
  55. tmp = q.top(); q.pop();
  56. if(vis[tmp.v])continue;
  57. vis[tmp.v] = true;
  58. for(int i = head[tmp.v]; ~i; i = edge[i].nxt)
  59. {
  60. int v = edge[i].to;
  61. if(dis[v] > dis[tmp.v] + edge[i].w)
  62. {
  63. dis[v] = dis[tmp.v] + edge[i].w;
  64. q.push(node(v, dis[v]));
  65. }
  66. }
  67. }
  68. }
  69. int main()
  70. {
  71. // double pp = clock();
  72. // freopen("233.in", "r", stdin);
  73. // freopen("233.out", "w", stdout);
  74. ios_base::sync_with_stdio(0);
  75. cin.tie(0);cout.tie(0);
  76. cin >> n;
  77. for(int i = 1; i <= 3; ++i)cin >> a[i];
  78. sort(a + 1, a + 1 + 3);
  79. if(a[1] == 1){
  80. cout << n << endl;
  81. return 0;
  82. }
  83. ll mi = a[1];
  84. init();
  85. for(int i = 0; i <= mi - 1; ++i)
  86. for(int j = 2; j <= 3; ++j)
  87. addedge(i, (i + a[j]) % mi, a[j]);
  88. dijkstra(1);
  89. ll ans = 0;
  90. for(int i = 0; i <= mi - 1; ++i)
  91. if(dis[i] <= n)
  92. ans += (n - dis[i]) / mi + 1;
  93. cout << ans << endl;
  94. return 0;
  95. }

遥远的旅途

题目

这题的大致思路是将dp问题用最短路来优化,,

dp[i][j] 表示从起点走到i时的长度为j的一条路是否存在,,但是空间都会爆掉,,

考虑第二维,假设是通过经过若干个环来达到T,,也就是 len+kw==T ,,这里的w即为环的长度的两倍,,如果取模w就是 len%w==T%w ,,这样子dp方程就变成了到达 i 点时路径长度取模等于j的一条路径的长度,,利用spfa来转移,,只要最后 dp[n][T%w] <= T 就表示存在解,这样子利用模数来压缩了状态,,找等同的就行了,,,参考 参考

  1. #include <bits/stdc++.h>
  2. #define aaa cout<<233<<endl;
  3. #define endl '\n'
  4. using namespace std;
  5. typedef long long ll;
  6. typedef unsigned long long ull;
  7. typedef long double ld;
  8. // mt19937 rnd(TM(0));
  9. const int inf = 0x3f3f3f3f;//1061109567 > 1e9
  10. const ll linf = 0x3f3f3f3f3f3f3f3f;
  11. const double eps = 1e-6;
  12. const double pi = 3.14159265358979;
  13. const int maxn = 1e2 + 5;
  14. const int maxm = 1e7 + 233;
  15. const int mod = 1e9 + 7;
  16. ll n, m, T, a[maxn], ww;
  17. struct edge
  18. {
  19. int to, nxt; ll w;
  20. }edge[maxn << 1];
  21. int tot, head[maxn << 1];
  22. void init()
  23. {
  24. tot = 0;
  25. memset(head, -1, sizeof head);
  26. }
  27. void addedge(int u, int v, ll w)
  28. {
  29. edge[tot].to = v;
  30. edge[tot].w = w;
  31. edge[tot].nxt = head[u];
  32. head[u] = tot++;
  33. }
  34. ll dp[maxn][20005];
  35. bool vis[maxn][20005];
  36. queue<pair<int, ll> > q;
  37. void spfa()
  38. {
  39. memset(dp, inf, sizeof dp);
  40. memset(vis, false, sizeof vis);
  41. while(!q.empty())q.pop();
  42. dp[1][0] = 0; vis[1][0] = true;
  43. q.push(make_pair(1, 0));
  44. while(!q.empty())
  45. {
  46. int u = q.front().first; ll w = q.front().second; q.pop();
  47. vis[u][w] = false;
  48. for(int i = head[u]; ~i; i = edge[i].nxt)
  49. {
  50. int v = edge[i].to; ll vw = edge[i].w;
  51. if(dp[v][(w + vw) % ww] > dp[u][w] + vw)
  52. {
  53. dp[v][(w + vw) % ww] = dp[u][w] + vw;
  54. if(!vis[v][(w + vw) % ww])
  55. {
  56. vis[v][(w + vw) % ww] = true;
  57. q.push(make_pair(v, (w + vw) % ww));
  58. }
  59. }
  60. }
  61. }
  62. }
  63. int main()
  64. {
  65. // double pp = clock();
  66. // freopen("233.in", "r", stdin);
  67. // freopen("233.out", "w", stdout);
  68. ios_base::sync_with_stdio(0);
  69. cin.tie(0);cout.tie(0);
  70. int t; cin >> t;
  71. while(t--)
  72. {
  73. cin >> n >> m >> T;
  74. int u, v, w;
  75. init();
  76. for(int i = 1; i <= m; ++i)
  77. {
  78. cin >> u >> v >> w;
  79. ++u, ++v;
  80. addedge(u, v, w);
  81. addedge(v, u, w);
  82. }
  83. bool flag = false;
  84. for(int i = head[n]; ~i; i = edge[i].nxt)
  85. {
  86. ww = edge[i].w << 1;
  87. spfa();
  88. if(dp[n][T % ww] <= T)
  89. {
  90. flag = true;
  91. break;
  92. }
  93. }
  94. if(flag)cout << "Possible" << endl;
  95. else cout << "Impossible" << endl;
  96. }
  97. return 0;
  98. }

(end)

ACM-图论-同余最短路的更多相关文章

  1. 【66测试20161115】【树】【DP_LIS】【SPFA】【同余最短路】【递推】【矩阵快速幂】

    还有3天,今天考试又崩了.状态还没有调整过来... 第一题:小L的二叉树 勤奋又善于思考的小L接触了信息学竞赛,开始的学习十分顺利.但是,小L对数据结构的掌握实在十分渣渣.所以,小L当时卡在了二叉树. ...

  2. [CF986F]Oppa Funcan Style Remastered[exgcd+同余最短路]

    题意 给你 \(n\) 和 \(k\) ,问能否用 \(k\) 的所有 \(>1\) 的因子凑出 \(n\) .多组数据,但保证不同的 \(k\) 不超过 50 个. \(n\leq 10^{1 ...

  3. HDU 6071 Lazy Running (同余最短路 dij)

    Lazy Running Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 524288/524288 K (Java/Others)To ...

  4. BZOJ 2118 墨墨的等式 (同余最短路)

    题目大意:已知B的范围,求a1x1+a2x2+...+anxn==B存在非负正整数解的B的数量,N<=12,ai<=1e5,B<=1e12 同余最短路裸题 思想大概是这样的,我们选定 ...

  5. 洛谷P3403跳楼机(最短路构造/同余最短路)

    题目-> 解题思路: 最短路构造很神啊. 先用前两个值跑在第三个值模意义下的同余最短路(这步贪心可以证明,如果第三步长为z,那么如果n+z可以达到,n+2z同样可以达到) 最后计算与楼顶差多少个 ...

  6. 【CodeChef】LECOINS(同余最短路,背包DP)

    题意:给定n个物品,每个物品可以取无限次,每个物品有两种属性:价值v和颜色c 现在有q个询问,每次询问是否能取出价值和为S的方案,如有多解输出不同颜色种数的最大值 题意:看到BZOJ评论区有好心人说C ...

  7. 【同余最短路】洛谷 P2662 牛场围栏

    关于同余最短路的部分 [同余最短路]P3403跳楼机/P2371墨墨的等式 [P2662牛场围栏] 题目背景 小L通过泥萌的帮助,成功解决了二叉树的修改问题,并因此写了一篇论文, 成功报送了叉院(羡慕 ...

  8. 【同余最短路】【例题集合】洛谷P3403 跳楼机/P2371 墨墨的等式

    接触到的新内容,[同余最短路]. 代码很好写,但思路不好理解. 同余最短路,并不是用同余来跑最短路,而是通过同余来构造某些状态,从而达到优化时间空间复杂度的目的.往往这些状态就是最短路中的点,可以类比 ...

  9. Codeforces 516E - Drazil and His Happy Friends(同余最短路)

    Codeforces 题面传送门 & 洛谷题面传送门 首先思考一个非常简单的性质:记 \(d=\gcd(n,m)\),那么每次在一起吃完饭的男女孩编号必定与 \(d\) 同余,而根据斐蜀定理可 ...

  10. Codeforces 986F - Oppa Funcan Style Remastered(同余最短路)

    Codeforces 题面传送门 & 洛谷题面传送门 感谢此题教会我一个东西叫做同余最短路(大雾 首先这个不同 \(k\) 的个数 \(\le 50\) 这个条件显然是让我们对每个 \(k\) ...

随机推荐

  1. 剑指offer】Java版代码(完整版)

    转自:剑指offer]Java版代码(完整版) 转自:[剑指offer] JAVA版题解(完整版)

  2. springboot---redis缓存的使用

    1.下载redis安装包,解压到电脑 2.启动redis 3.springboot  application.properties中配置redis缓存 spring.redis.host=127.0. ...

  3. 一文轻松搞懂Vuex

    概念: Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式(官网地址:https://vuex.vuejs.org/zh/).它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状 ...

  4. Java第二次作业第一题

    编写图形界面程序,在窗体中设置菜单栏,在菜单栏上添加"file"菜单,在文件菜单中添加"new"和"quit"两个菜单项,其中"q ...

  5. Centos7 设置redis开机自启

    Centos7 设置redis开机自启 标签(空格分隔):Linux 环境 Centos7.1 redis-3.0.6 chkconfig方式 **service和chkconfig命令的功能好像都被 ...

  6. 解决Android数据库异步操作的大问题

    前言 相信大家在开发过程中,也遇到过下面的这种异常: java.lang.IllegalStateException: attempt to re-open an already-closed obj ...

  7. [C++] 头文件中不要用using namespace std

    先总结下: 1. using namespce std:尽量不要(或者强硬一点,不许)在头文件中使用. 解析: 不让这么用,主要原因就是防止名字重复(即自定义变量名和std中名字重复),因为头文件会被 ...

  8. ZooKeeper单机客户端的启动流程源码阅读

    客户端的启动流程 看上面的客户端启动的脚本图,可以看到,zookeeper客户端脚本运行的入口ZookeeperMain.java的main()方法, 关于这个类可以理解成它是程序启动的辅助类,由它提 ...

  9. UnicodeDecodeError: 'gbk' codec can't decode byte 0xb0 in position 279: illegal multibyte sequence

    with open(r'E:\yy\mysql.txt') as wk: print(wk.readlines()) Traceback (most recent call last): File & ...

  10. 搭建大数据开发环境-Hadoop篇

    前期准备 操作系统 hadoop目前对linux操作系统支持是最好的,可以部署2000个节点的服务器集群:在hadoop2.2以后,开始支持windows操作系统,但是兼容性没有linux好.因此,建 ...