YBTOJ 6.3同余问题

A.同余方程

image
image

详见扩展欧几里得算法学习笔记

点击查看代码
#include <bits/stdc++.h>
#define ll long long
using namespace std;

void exgcd(ll a, ll b, ll &x, ll &y) {
	if (b == 0) {
		x = 1;
		y = 0;
		return;
	}
	exgcd(b, a % b, x, y);
	ll z = x;
	x = y;
	y = z - (a / b) * y;
}

int main() {
	ll a, b, x, y;
	scanf("%lld%lld", &a, &b);
	exgcd(a, b, x, y);
	x = (x + b) % b;
	printf("%lld",x);
	
	return 0;
}

B.约数之和

image
image

考虑算术基本定理

i=1nj=0b×cipij

根据等比数列求和公式 得

i=1n(pib×ci+11pi1)

考虑 pi19901 不互质的情况
则有 pi10(mod 9901)
pi1(mod 9901)
那么对于任意 x 都有 pix1(mod 9901)
那么显然 j=0b×cipijmod9901=b×ci+1

点击查看代码
#include <bits/stdc++.h>
#define ll long long

using namespace std;

const ll mod = 9901;
ll a, b, ans = 1;
int tot;

ll ksm(ll x, ll y) {
	ll ret = 1;
	while (y) {
		if (y & 1) ret = ret * x % mod;
		x = x * x % mod;
		y >>= 1;
	}
	return ret;
}

ll inv(ll x) {
	return ksm(x, mod - 2);
}

void work(ll x, ll y) {
	if ((x - 1) % mod == 0) ans = (ans * (b + 1) % mod) % mod;
	else ans = (ans * (ksm(x, y + 1) - 1) % mod * inv(x - 1)) % mod;
}

int main() {
	scanf("%lld%lld", &a, &b);
	for (ll i = 2; i * i <= a; ++i) {
		if (a % i == 0) {
			int num = 0;
			while (a % i == 0) {
				a /= i;
				num++;
			}
			work(i, num * b);
		}
	}
	if (a > 1) work(a, 1 * b);
	printf("%lld",ans);
	
	return 0;
}

C.线性求逆元

image
image

  • 解法1

考虑构造 mod=modx×x+r

转化为 modx×x+r0(mod mod)

同乘 x1×r1
modx×r1+x10(mod mod)

所以有
x1modx×r1(mod mod)

由于 r=modmodx

显然 r<x

也就是说我们已经知道了 r1 就可以直接求出 x1

inv[1] = 1;
for (int i = 2; i <= n; ++i) {
	inv[i] = ((p - p / i) * inv[p % i] + p) % p;
}
  • 解法二

来自 @rabbit_lb 可用来求阶乘的逆元

首先用快速幂求出 n!1
那么 (n1)!1=n!1×n
然后一直推下去即可


D.中国剩余定理

image
image

这章怎么全是板子题

详见中国剩余定理学习笔记

点击查看代码
#include <bits/stdc++.h>
#define ll long long
using namespace std;

const int N = 11;
ll a[N], b[N];
ll pai = 1;
int k;
ll ans;

ll ksc(ll x, ll y) {
	ll ret = 0;
	while (y) {
		if (y & 1) ret = (ret + x) % pai;
		x = (x + x) % pai;
		y >>= 1;
	}
	return ret;
}

void exgcd(ll a, ll b, ll &x, ll &y) {
	if (b == 0) {
		x = 1;
		y = 0;
		return;
	}
	exgcd(b, a % b, x, y);
	ll z = x;
	x = y;
	y = z - (a / b) * y;
}

int main() {
	scanf("%d", &k);
	for (int i = 1; i <= k; ++i) scanf("%lld%lld", &b[i], &a[i]);
	for (int i = 1; i <= k; ++i) pai *= b[i];
	
	for (int i = 1; i <= k; ++i) {
		ll x, y;
		exgcd(pai / b[i], b[i], x, y);
		x = (x % b[i] + b[i]) % b[i];
		a[i] = (a[i] % b[i] + b[i]) % b[i];
		ans = (ans + ksc(pai / b[i] * x, a[i])) % pai;
	}
	
	printf("%lld", ans);
	
	return 0;
}
posted @   Steven24  阅读(79)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示