202. 最幸运的数字
欧拉筛+快速幂
由8组成的数字可以表示为: 8 ∗ ( 1 0 x − 1 ) / 9 8*(10^x-1)/9 8∗(10x−1)/9
根据题意有: L ∣ 8 ∗ ( 1 0 x − 1 ) / 9 L~~| ~~8*(10^x-1)/9 L ∣ 8∗(10x−1)/9
转化:
9 L ∣ 8 ∗ ( 1 0 x − 1 ) 9L~~|~~8*(10^x-1) 9L ∣ 8∗(10x−1)
令 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∗(10x−1)/d
因为 8/d 和 9L/d 互质,所以 9L/d 一定是 (10^x-1) 的因子,所以
9 L / d ∣ ( 1 0 x − 1 ) 9L/d~~|~~(10^x-1) 9L/d ∣ (10x−1)
即:
( 1 0 x − 1 ) ≡ 0 ( m o d 9 L / d ) (10^x-1)≡0~(mod~9L/d) (10x−1)≡0 (mod 9L/d)
等于:
1 0 x ≡ 1 ( m o d 9 L / d ) 10^x≡1~(mod~9L/d) 10x≡1 (mod 9L/d)
所以我们要求的是最小的x
根据引理:若正整数 a,n 互质,则满足 a x ≡ 1 ( m o d n ) a^x≡1~(mod~n) ax≡1 (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
x即为a在mod b意义下的逆元,可以将同余方程化为ax+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
所以可以用扩展欧几里得算法来求出x,求出的∣x∣+∣y∣是最小的,如果ab=0,还可以知道∣x∣≤b且∣y∣≤a。但并不能保证x是正数,需要进行x=(b+x%b)%b的操作来得到最小正整数x
#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/