思路分析: 设由x个8构成的x位数能够被L整除, d = gcd(L, 8),
则
, 分析知10与互质.引理: 若正整数a, n互质, 则满足
的最小正整数为的约数, 为欧拉函数. 证明从略:因此只需枚举
的所有约数, 并使用快速幂检验即可, 需要注意的是快速幂计算乘法的中间结果会超出long long最大表示范围, 需单独写一个64位整数乘法的过程, 具体实现如下AC代码所示:
//POJ3696_The Luckiest number
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
using namespace std;
typedef long long ll;
//返回(a * b) % mod的值
ll mul(ll a, ll b, ll mod){
ll res = 0;
for(; b; b >>= 1, a = (a << 1) % mod) if(b & 1) res = (res + a) % mod;
return res;
}
ll power(ll a, ll b, ll mod){
ll res = 1;
for(; b; b >>= 1, a = mul(a, a, mod)) if(b & 1) res = mul(res, a, mod);
return res;
}
int gcd(int a, int b){
if(!b) return a;
return gcd(b, a % b);
}
//将n的所有约数存储于approx中
void getApprox(ll n, vector<ll> &approx){
for(int i = 1; i <= sqrt((double)n); ++i){
if(n % i) continue;
approx.push_back(i);
if(i != n / i) approx.push_back(n / i);
}
}
//返回n的欧拉函数值
ll euler(ll n){
ll res = n;
for(int i = 2; i <= sqrt((double)n); ++i){
if(n % i) continue;
res = res / i * (i - 1);
while(n % i == 0) n /= i;
}
if(n >= 2) res = res / n * (n - 1);
return res;
}
int main(){
int sn = 0, L;
while(++sn, scanf("%d", &L), L){
ll tmp = (9ll * L) / gcd(L, 8); int res = 0;
vector<ll> approx; getApprox(euler(tmp), approx);
sort(approx.begin(), approx.end());
for(int i = 0; i < approx.size(); ++i){
ll t = power(10, approx[i], tmp);
if(t == 1){
res = approx[i]; break;
}
}
cout << "Case " << sn << ": " << res << endl;
}
return 0;
}
来源:CSDN
作者:solider98
链接:https://blog.csdn.net/solider98/article/details/85713745