同余方程
x和y的最大公约数是d
(x,y)=d
转化成方程
ax+by=d
参数x和y相关的表达式 x y正负不管
x=x0+kb/d (对方的那坨来加的)
y=y0-ka/d
//拓展欧几里得
int exgcd(int a, int b, int &x, int &y)//ax=d%(mod b) x和y是ax+by=d 方程的一组可行解 返回值是最大公约数(最后一层的a)
{
if (!b)
{
x = 1, y = 0;
return a;
}
int d = exgcd(b, a % b, y, x);
y -= a / b * x;
return d;
}
同余方程 求 ax=1(mod d) 的x的整数解 这里最大公约数就是1 ax+yd=1
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
int exgcd(int a, int b, int &x, int &y)
{
if (!b)
{
x = 1, y = 0;
return a;
}
int d = exgcd(b, a % b, y, x);
y -= a / b * x;
return d;
}
int main()
{
int a, b;
cin >> a >> b;
int x, y;
exgcd(a, b, x, y);
cout << (x % b + b) % b << endl;
return 0;
}
青蛙约会 围着一圈 a在a点一次能跑m米,b在b点一次跑n米 一圈是L 求x跑了多少秒追上b
https://www.acwing.com/activity/content/problem/content/1753/
a:青蛙a的起点
b:青蛙b的起点
m:青蛙a一次能跳多远
n:青蛙b一次能跳多远
L:一圈的距离
(b-a):a要追b多少米
(m-n):每跳一次,a能追b多少米
x是总共跳了多少次
y是a追b不一定会在一圈内追完,而是追了y圈
(m - n)x = b - a + yL
(m - n)x - yL = b - a
——————— — —————
已知 已知 已知
扩展欧几里得求的是
ax+by=d
a已知,b已知,d是a和b的最大公约数,求x,y
因此把上式的a替换乘(m-n),b替换成L。
式子变成(m-n)x+(-y)L=d
LL d = exgcd(m - n, L, x, y);
如果(b-a)%d不等于0,两只青蛙永远不会碰面,不是最大公约数
如果(b-a)%d等于零,把(m-n)x+(-y)L=d扩大(b-a)/d倍后,x就是结果。
//x0放大是因为 x0是(m-n)x-yl=gcd(m-n,l) 的方程的解 而答案要求的是
//(m-n)x-yl=b-a的b-a,此x0非彼x0,所以只有x0的问题是需要放大的
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
LL exgcd(LL a, LL b, LL &x, LL &y)
{
if (!b)
{
x = 1, y = 0;
return a;
}
LL d = exgcd(b, a % b, y, x);
y -= a / b * x;
return d;
}
int main()
{
LL a, b, m, n, L;
cin >> a >> b >> m >> n >> L;
LL x, y;
LL d = exgcd(m - n, L, x, y);
if ((b - a) % d) puts("Impossible");
else
{
x *= (b - a) / d;
LL t = abs(L / d);
cout << (x % t + t) % t << endl;
}
return 0;
}
最幸运的数 求多少个8连接在一起可以变成c的倍数 https://www.acwing.com/problem/content/204/
变成求 9L |8×(10^x−1) 的最小正整数 x
最终变成求解满足 10^x≡1(modC) 的最小正整数 x
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
using namespace std;
typedef long long LL;
LL qmul(LL a, LL k, LL p) {
LL res = 0;
while (k) {
if (k & 1) res = (res + a) % p;
k >>= 1;
a = (a + a) % p;
}
return res;
}
LL get_euler(LL C) {
LL res = C;
for (LL i = 2; i <= C / i; i ++ )
if (C % i == 0) {
while (C % i == 0) C /= i;
res = res / i * (i - 1);
}
if (C > 1) res = res / C * (C - 1);
return res;
}
LL qmi(LL a, LL k, LL p) {
LL res = 1;
while (k) {
if (k & 1) res = qmul(res, a, p);
k >>= 1;
a = qmul(a, a, p);
}
return res;
}
LL gcd(LL a, LL b) {
return b ? gcd(b, a % b) : a;
}
int main() {
int T = 1;
LL L;
while (cin >> L, L) {
int d = 1;
while (L % (d * 2) == 0 && d * 2 <= 8) d *= 2;
// 求C 和 phi(C)
LL C = 9 * L / d;
LL phi = get_euler(C);
LL res = 1e18;
// 用gcd有一定的常数,因为C较大
// if (gcd(10, C) != 1) res = 0;
// 判断10和C是否互质,不互质输出0
if (C % 2 == 0 || C % 5 == 0) res = 0;
// 枚举phi(C)的所有约数
for (LL d = 1; d * d <= phi; d ++ ) // 约数d可能爆int 根号枚举
if (phi % d == 0) {//如果是约数
if (qmi(10, d, C) == 1) res = min(res, d);//膜等于1的话
if (qmi(10, phi / d, C) == 1) res = min(res, phi / d);
}
printf("Case %d: %lld\n", T ++ , res);
}
return 0;
}