同余

202. 最幸运的数字

在这里插入图片描述
在这里插入图片描述
欧拉筛+快速幂

由8组成的数字可以表示为: 8 ∗ ( 1 0 x − 1 ) / 9 8*(10^x-1)/9 8(10x1)/9

根据题意有: L    ∣    8 ∗ ( 1 0 x − 1 ) / 9 L~~| ~~8*(10^x-1)/9 L    8(10x1)/9

转化:

9 L    ∣    8 ∗ ( 1 0 x − 1 ) 9L~~|~~8*(10^x-1) 9L    8(10x1)

d = g c d ( 8 ,   L ) d = gcd(8, ~L) d=gcd(8, L)

有: 9 L / d    ∣    8 ∗ ( 1 0 x − 1 ) / d 9L/d~~|~~8*(10^x-1)/d 9L/d    8(10x1)/d

因为 8/d 和 9L/d 互质,所以 9L/d 一定是 (10^x-1) 的因子,所以

9 L / d    ∣    ( 1 0 x − 1 ) 9L/d~~|~~(10^x-1) 9L/d    (10x1)

即:

( 1 0 x − 1 ) ≡ 0   ( m o d   9 L / d ) (10^x-1)≡0~(mod~9L/d) (10x1)0 (mod 9L/d)

等于:

1 0 x ≡ 1   ( m o d   9 L / d ) 10^x≡1~(mod~9L/d) 10x1 (mod 9L/d)

所以我们要求的是最小的x

根据引理:若正整数 a,n 互质,则满足 a x ≡ 1   ( m o d   n ) a^x≡1~(mod~n) ax1 (mod n) 的最小正整数 x 是 phi(n) 的约数。

所以只需要枚举约数是否满足条件即可,有可能会出现没有答案的情况,此时输出 0

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

ll l;

ll euler_phi(ll n)
{
	ll res = n;
	for (int i = 2; i * i <= n; i++){
		if (n % i == 0){
			res = res / i * (i - 1);
			for ( ; n % i == 0; n /= i);
		}
	}	
	if (n != 1)
		res = res / n * (n - 1);
	return res;
}

ll mod_mul(ll a, ll b, ll mod)
{
	ll res = 0;
	a %= mod, b %= mod;
	while (b > 0) {
		if (b & 1) res = (res + a) % mod;
		a = a * 2 % mod;
		b >>= 1;
	}
	return res;
}

ll mod_pow(ll x, ll n, ll mod)
{
	ll res = 1; 
	while (n > 0) {
		if (n & 1) res = mod_mul(res, x, mod);
		x = mod_mul(x, x, mod);
		n >>= 1;
	}
	return res % mod;
}

int main(void)
{
	ll idx = 1, res;
	while (cin >> l && l) {
		res = 1e18;
		ll mod = 9 * l / __gcd((ll)8, l);
		ll phi = euler_phi(mod);
		
		for (ll i = 1; i * i <= phi; i++) {
			if (phi % i == 0) {
				if (mod_pow(10, i, mod) == 1) {
					res = min(res, i);
				}
				if (mod_pow(10, phi / i, mod) == 1) {
					res = min(res, phi / i);
				} 
			}
		}
		printf("Case %lld: ", idx++);
		printf("%lld\n", res == 1e18 ? 0 : res);
	}
	
	return 0;
}

203. 同余方程

在这里插入图片描述
x 即 为 a 在 m o d   b 意 义 下 的 逆 元 , 可 以 将 同 余 方 程 化 为 a x + b y = 1 x即为a在mod~b意义下的逆元,可以将同余方程化为ax+by=1 xamod bax+by=1
所 以 可 以 用 扩 展 欧 几 里 得 算 法 来 求 出 x , 求 出 的 ∣ x ∣ + ∣ y ∣ 是 最 小 的 , 如 果 a b ≠ 0 , 还 可 以 知 道 ∣ x ∣ ≤ b 且 ∣ y ∣ ≤ a 。 但 并 不 能 保 证 x 是 正 数 , 需 要 进 行 x = ( b + x % b ) % b 的 操 作 来 得 到 最 小 正 整 数 x 所以可以用扩展欧几里得算法来求出x,求出的|x|+|y|是最小的,如果ab\neq 0,还可以知道|x|\leq b且|y|\leq a。但并不能保证x是正数,需要进行x=(b+x\%b)\%b的操作来得到最小正整数x xx+yab=0xbyaxx=(b+x%b)%bx

#include <cstdio>
#include <iostream>
using namespace std;

int exgcd(int a, int b, int& x, int& y)
{
	int d = a;
	if (b != 0){
		d = exgcd(b, a % b, y, x);
		y -= (a / b) * x;
	}
	else{
		x = 1;
		y = 0;
	}
	return d;
}

int main(void)
{
	int a, b, x, y;
	cin >> a >> b;
	exgcd(a, b, x, y);
	x = (b + x % b) % b;
	cout << x << endl;
	
	return 0;
}

204. 表达整数的奇怪方式

在这里插入图片描述

中国剩余定理

题解:https://www.acwing.com/solution/content/3539/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值