多组测试样例,给定一个L,求位数最少的全由8组成的数是L的倍数,输出时加上"Case t: "
数据范围:
1 ≤ L ≤ 2*109
# 题解
x位数字每一位是8的数字表示为8*(10x-1)/9
10x有x+1位,-1为x位由9构成,再除9就是x位由1构成的数字,乘8就是由x位8构成的数字
即转化成了求最小的x使得
L|8*(10x-1)/9
L*k=8*(10x-1)/9
9*L*k=8*(10x-1)
gcd(9*L,8)=gcd(L,8)=d
(9*L)/d * k=8/d*(10x-1)
u=(9*L)/d ,v=8/d
u*k=v*(10x-1)
因为除了最大公约数所以u、v互质
因为u<v
u | (10x-1)
即10x-1 ≡ 0(mod u)
10x ≡ 1 (mod (9L/d))
欧拉定理中aφ(n) ≡ 1 (mod n),a和n互质
所以必定存在一个和10互质的u满足上式
但是只用欧拉定理无法求出最小的解
引理:
正整数a,n互质,则满足ax ≡ 1 mod( n )的最小正整数x0是φ(n)的约数
直观上将欧拉定理的φ(n)拆成φ(n) , ax*y≡ 1 mod( n )
反证法证明:
将φ(n)拆解成x*k+y,假设x为满足方程最小的值且x>y>0, x*k <φ(n) ,
ax*k+y≡ 1 mod( n )
ax ≡ 1 mod( n )
ax*k*ay≡ 1 mod( n )
ay≡ 1 mod( n )
那么存在更小的y,矛盾
最后因为数很大1010*1010 就会爆掉long long,乘法改用龟速乘及时取模防止溢出
时间复杂度为O(√u) umax=(9*2*109)/d = (1.8 * 1010)/d,d最小为2 约为1010
1 #include <bits/stdc++.h> 2 #define ll long long 3 using namespace std; 4 const int N=1e4; 5 ll L; 6 int n; 7 ll gcd(ll a, ll b){return b?(b,a%b):a;} 8 ll get_phi(ll x){ 9 ll res=x; 10 for(ll i=2;i*i<=x;i++){ 11 if(x%i==0){ 12 res=res/i*(i-1); 13 while(x%i==0) x/=i; 14 } 15 } 16 if(x>1) res=res/x*(x-1); 17 return res; 18 } 19 ll qmul(ll a, ll k, ll p){ 20 ll res=0; 21 while(k){ 22 if(k&1) res=(res+a)%p; 23 a=(a+a)%p; 24 k>>=1; 25 } 26 return res; 27 } 28 ll qmi(ll a,ll k ,ll p){ 29 ll res=1; 30 while(k){ 31 if(k&1) res=qmul(res,a,p);//会爆long long 32 a=qmul(a,a,p);//会爆long long 33 k>>=1; 34 } 35 return res; 36 } 37 int main(){ 38 while(scanf("%lld",&L),L){ 39 printf("Case %d: ",++n); 40 ll d=gcd(L,8); 41 ll u=L/d*9; 42 if(gcd(u,10)!=1) {printf("0");return 0;} 43 ll phi=get_phi(u); 44 ll ans=1e18; 45 for(ll i=1;i<=phi/i;i++){ 46 if(phi % i==0){ 47 if(qmi(10,i,u)==1) ans=min(ans,i); 48 if(qmi(10,phi/i,u)==1) ans=min(ans,phi/i); 49 } 50 } 51 printf("%lld ",ans); 52 } 53 }