HIT2815Min Chain扩展欧几里德
来源:互联网 发布:人工智能导论教学大纲 编辑:程序博客网 时间:2024/05/16 10:50
题目:http://acm.hit.edu.cn/hoj/problem/view?id=2815
题意:给定两个数和,其中,只对和进行加减操作,求最少需要多少步能得到1。
分析:典型的扩展欧几里得算法,注意有些需要特判。
小结:
看到一篇博客说 : a*x+b*y==gcd(a,b)成立的式子的特解:x1,y1,满足:x=x1+t*b,y=y1+t*b,且|x1|<b,|y1|<a
因为题目要求的是|x1|+|y1|最小,故此:当x1<0时比较|x1+b|+|y1-a|和x1,y1 的大小取小的,当x1>0时,比较|x1-b|+|y1+a|和x1,y1 的大小取小的。
对于上面的|x1|<b,|y1|<a这个结论,我也不知道到底是对还是错,网上的题解几乎都采用了这种意思的做法。感觉上貌似是对的,但是也不知道怎么证明。
如果希望更保险的做法的话,还是用手动将x转化为正的最小,转化y时也一样:
#include <iostream>#include <string.h>#include <algorithm>#include <stdio.h>using namespace std;typedef long long LL;LL gcd(LL a,LL b){ return b ? gcd(b,a%b):a;}void extend_Euclid(LL a,LL b,LL &x,LL &y){ if(b == 0) { x = 1; y = 0; return; } extend_Euclid(b,a%b,x,y); LL tmp = x; x = y; y = tmp - (a / b) * y;}int main(){ int T; cin>>T; while(T--) { LL a,b; cin>>a>>b; if(a < b) swap(a,b); LL g = gcd(a,b); if(g != 1) { puts("-1"); continue; } if(b == 1 && a == 2) { puts("1"); continue; } if(b == 1) { puts("2"); continue; } if(b == 0 && a == 1) { puts("1"); continue; } LL x,y; extend_Euclid(a,b,x,y); LL ans = abs(x) + abs(y); if(x < 0) { x = (x%b + b) % b; LL ty = (1-a*x) / b; if(ty < 0) ty = -ty; LL tmp = x + ty; if(tmp < ans) ans = tmp; } else { y = (y%a + a) % a; LL tx = (1-b*y) / a; if(tx < 0) tx = -tx; LL tmp = y + tx; if(tmp < ans) ans = tmp; } cout<<ans - 1<<endl; } return 0;}
网上类似于结论性的写法:
#include<iostream>#include<algorithm>#include<cstring>#include<cstdio>using namespace std;typedef long long ll;ll gcd(ll a, ll b){ return b ? gcd(b, a%b) : a;}void extend_Euclid(ll a, ll b, ll &x, ll &y){ if(b == 0) { x = 1; y = 0; return ; } extend_Euclid(b, a%b, x, y); ll tmp = x; x = y; y = tmp - (a/b)*y;}int main(){ int T; cin >> T; while(T--) { ll a, b; cin >> a >> b; if(a < b) swap(a, b); ll g = gcd(a, b); if(g != 1) { puts("-1"); continue; } if(a == 2 && b == 1) { puts("1"); continue; } if(b == 1) { puts("2"); continue; } if(b == 0 && a == 1) { puts("1"); continue; } ll x, y; extend_Euclid(a, b, x, y); ll ans = abs(x) + abs(y); if(x < 0) { ll tmp = abs(x+b) + abs(y-a); if(tmp < ans) ans = tmp; } else { ll tmp = abs(x-b) + abs(y+a); if(tmp < ans) ans = tmp; } cout << ans - 1 << endl; } return 0;}
0 0
- HIT2815Min Chain扩展欧几里德
- 欧几里德和扩展欧几里德
- 欧几里德, 与 扩展欧几里德
- 欧几里德|扩展欧几里德
- 欧几里德&&扩展欧几里德详解
- 欧几里德&&扩展欧几里德
- 扩展欧几里德
- 扩展欧几里德
- 扩展欧几里德
- 扩展欧几里德
- 扩展欧几里德
- 扩展欧几里德
- 扩展欧几里德
- 扩展欧几里德
- 扩展欧几里德
- 扩展欧几里德!!!!!
- 扩展欧几里德
- 扩展欧几里德
- nginx+tomcat实现代理访问java web项目
- ubuntu中运行jupyter notebook创建Python文件的时候报错
- 怎么解决文中写一个字,却要替换掉后一个字的问题
- 机器学习图像识别数据挖掘面试中 不会的&答错的&答得不好的 问题Mark1
- zjoi2017day2酱油记
- HIT2815Min Chain扩展欧几里德
- Visual Studio 保存布局等个人习惯
- 大数阶乘
- 排序15:有序矩阵查找
- MATLAB画图函数plot简单用法
- 第十一周:( LeetCode474) Ones and Zeroes(c++)
- 文章标题
- 排序16:最短子数组
- 清除浮动方法