Description
题意:给你一个数L,让你求出最小的一个数能被L整除,这个数满足每一位都是8。
input
8
11
16
0
output
Case 1: 1
Case 2: 2
Case 3: 0
所用数论知识:
- 欧拉同余定理
- 欧拉函数
- 质数筛法
第一步列式 :(10 ^ x - 1) / 9是x个连续的8的表达
代码如下
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#define il inline
#define re register
using namespace std;
typedef long long ll;
const ll maxn = 50010;
ll L, ans, tot;
ll q, d, p;
//推公式使用到的数
ll v[maxn], vis[maxn];
//v => 保存L以内所有质数
vector<ll> T;
il void Prime() {
memset(vis, 0, sizeof(vis));
ll k = 0;
for(re ll i = 2; i < maxn; ++i) {
if(!vis[i]) {
v[k++] = i;
for(re ll j = i+i; j < maxn; j += i)
vis[j] = 1;
}
}
return ;
}
il ll GetEuler(ll x) {
ll res = x;
for(re ll i = 0; v[i]*v[i] <= x; ++i) {
if(x % v[i] == 0) {
res = res/v[i] * (v[i]-1);
while(x%v[i] == 0)
x /= v[i];
}
}
if(x > 1)//为质数
res = res/x * (x-1);
return res;
}
il ll GetGcd(ll a, ll b) {
return b==0 ? a : GetGcd(b, a%b);
}
il ll Mul(ll x, ll a, ll mod) {
ll res = 0;
while(a > 0) {
if(a & 1)
res = (res + x) % mod;
x = (x + x) % mod;
a >>= 1;
}
return res % mod;
}
il ll Pow(ll x, ll a, ll mod) {
ll res = 1;
while(a > 0) {
if(a & 1)
res = Mul(res, x, mod) % mod;
x = Mul(x, x, mod) % mod;
a >>= 1;
}
return res % mod;
}
il void Pre(ll L) {
T.clear();
for(re ll i = 0; v[i]*v[i] <= L; ++i) {
while(L % v[i] == 0) {
T.push_back(v[i]);
L /= v[i];
}
}
if(L > 1) T.push_back(L);
return ;
}
int main() {
tot = 0; Prime();
while(scanf("%lld", &L) && L != 0) {
printf("Case %lld: ", ++tot);
d = GetGcd(8, L);
//cout << d << endl;
q = 9*L/d;
//cout << q << endl;
//注意判断不合法的条件
if(GetGcd(q, 10) != 1) printf("0\n");
else {
ll cnt = GetEuler(q);
//cout << cnt << endl;
ll mi = cnt;
bool flag = 1;
while(flag) {
Pre(cnt);
flag = 0;
for(re ll i = 0; i < T.size(); ++i) {
if(Pow(10, cnt/T[i], q) == 1) {
flag = 1;
mi = min(mi, cnt/T[i]);
}
}
cnt = mi;
}
printf("%lld\n", mi);
}
}
return 0;
}