Water(扩欧求特解与通解)
题意:给容量分别为A与B的水杯,问确切喝到C水的最小操作次数
有4种操作:选一杯全喝,选一杯全部倒掉,选一杯装满,将一杯的水尽量倒到另一杯中
思路:只有Ax+By=C有解时才能确切喝到X水
裴蜀定理:如果a、b是整数,那么一定存在整数x、y使得ax+by=k*gcd(a,b)。
思路:要求x,y的特解,可以使用exgcd的板子,令c = k * gcd(A, B)则Ax + By = c;exgcd求出来的是k = 1时的特解
只要将x *= c / gcd(A, B), y *= c / gcd(A, B);此时x和y就是方程Ax + By = c的特解
这里有一个步长的概念对于x他的步长是 B / gcd(A, B), 对于y他的步长是 A / gcd(A, B)
要求最小整数解,只需要把x除上他的步长就能知道x要走多少步才能最接近0,再把x -= 步长 * 步数就可以让x最接近0,然
后在对原点附近的 (x+t⋅步长,y−t⋅步长)求min即可得到最小整数解
#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
#define ios ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr)
typedef pair<int, int> pr;
#define int long long
#define ll long long
#define fr(i,l,r) for(int i=l;i<=r;i++)
#define ufr(i,n,z) for(int i = n;i >= z; i--)
#define pb(x) push_back(x)
#define all(a) a.begin(),a.end()
#define fi first
#define se second
const int N = 1e6 + 10;
const int mod = 998244353, inf = LONG_LONG_MAX;
int dx[] = { 0,0,-1,0,1 }, dy[] = { 0,-1,0,1,0 };
int n, m;
int a[N];
int gcd(int a, int b) { //辗转相除
return !b ? a : gcd(b, a % b);
}
int exgcd(int a, int b, int& x, int& y) //扩欧板子
{
if (b == 0) {
x = 1; y = 0;
return a; //到达递归边界开始向上一层返回
}
ll d = exgcd(b, a % b, y, x);
y -= (a / b) * x;
return d;
}
void solve()
{
int a, b, c;
cin >> a >> b >> c;
if (c % gcd(a, b) != 0) {
cout << -1 << '\n'; //无解
}
else {
int x, y;
int d = exgcd(a, b, x, y);
x *= c / d; y *= c / d; //特解(除去最大公约数乘上C)
int dx = b / d; int dy = a / d;
y += (x / dx) * dy;
x -= (x / dx) * dx; //最小整数解,只需要把x除上他的步长就能知道x要走多少步才能最接近0
int ans = inf;
fr(i, -10, 10) {
int xx = x + dx * i; int yy = y - dy * i; //通解
ans = min(ans, max((xx + yy) << 1, (abs(xx - yy) << 1) - 1));
}
cout << ans << '\n';
}
}
signed main()
{
// ios;
int t = 1;
cin >> t;
while (t--) solve();
return 0;
}
P1082 [NOIP2012 提高组] 同余方程
题意:求ax->1(mod b)的最小整数解,输入数据保证一定有解。
转变为ax=1+by,移项ax-by=1,
扩欧求的特解x/d,y/d,文章来源:https://www.toymoban.com/news/detail-607669.html
通解x/d-i*(x/d/b/d)*b/d->x/d-x/b*(b/d)->x/d-i*x/d
文章来源地址https://www.toymoban.com/news/detail-607669.html
#include<iostream>
#define int long long
using namespace std;
int exgcd(int a, int b, int& x, int& y) {
if (b == 0) {
x = 1, y = 0;
return a;
}
int d = exgcd(b, a % b, y, x);
y -= (a / b) * x;
return d;
}
signed main(){
int a, b;
int x, y;
cin >> a >> b;
exgcd(a, b, x, y);
cout << (x % b + b) % b << '\n';
return 0;
}
到了这里,关于2023.7.26(同余方程的通解与特解)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!