You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

78 lines
2.7 KiB

2 years ago
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define endl "\n"
// 最大公约数
int gcd(int a, int b) {
if (b == 0) return a;
return b ? a : gcd(b, a % b);
}
// 快速乘
int ksc(int a, int b, int mod) {
int res = 0;
while (b) {
if (b & 1) res = (res + a) % mod;
a = (a + a) % mod;
b >>= 1;
}
return res;
}
// 快速幂+快速乘
int ksm(int a, int b, int mod) {
int res = 1;
while (b) {
if (b & 1) res = ksc(res, a, mod);
a = ksc(a, a, mod);
b >>= 1;
}
return res;
}
/**
*
* @param x
* @return
*/
int phi(int x) {
int res = x;
for (int i = 2; i <= x / i; i++)
if (x % i == 0) {
res = res / i * (i - 1);
while (x % i == 0) x /= i;
}
if (x > 1) res = res / x * (x - 1);
return res;
}
signed main() {
int T = 1; // 准备输出Case i
int L;
while (cin >> L, L) {
int d = gcd(L, 8); // L和8的最大公约数 gcd(8,L)
int mod = 9 * L / d; // 公式推导得到的mod
int p = phi(mod); // 单个数字mod的欧拉函数值φ(mod)
int res = LONG_LONG_MAX; // 预求最小先设最大
if (gcd(mod, 10) > 1) // 判断mod和10是否互质,不互质:方程无解输出0
res = 0;
else {
for (int d = 1; d * d <= p; d++) // 枚举φ(p)的每个小约数,到sqrt(φ(p))
if (p % d == 0) { // 如果d是约数,那么其实我们一次发现了两个约数: d 和 phi/d
// 这里与原来的质因子分解有一点点不同因为那个只要枚举小于sqrt(n)的,并且 n %d==0,
// 就一定是它的小质数因子,本题不是这个意思。
// 本题的目标是找出所有因子,注意,不是小因子。
// 因为,小因子不见得能是方程的解,大因子不见得不是方程的解!!
// 对于它们都有机会成为答案需要全部讨论到然后PK最小值即可
// 如果这个约数d满足 10 ^ d ≡ 1 (mod p) ,那么它有机会成为答案
if (ksm(10, d, mod) == 1) res = min(res, d); // 小约数
// 如果这个约数phi/d满足 10 ^ (phi/d) ≡ 1 (mod p) ,那么它有机会成为答案
if (ksm(10, p / d, mod) == 1) res = min(res, p / d); // 大约数
}
}
// 输出
printf("Case %d: %lld\n", T++, res);
}
}