思路:
数学推理
连续8组成的数字的表示方法:8*(10^k-1)/9
则n | 8*(10^k-1)/9
则9n | 8*(10^k-1)
令d=gcd(n,8)
则9n/d | 8/d*(10^k-1)
由于8和9互素,8和n同除以了他们的最大公约数,所以8和9n没有了除1以外的公约数,所以若要能整除9n/d的必然是(10^k-1)
则9n/d | 10^k-1
则10^k-1 % 9n/d == 0
则10^k-1 = k*(9n/d)
则10^k=k*(9n/d)+1
则10^k = 1 (mod 9n/d)
令c=9n/d,a=10则a^k=1 (mod c)
这个式子很容易让人联想到欧拉定理的形式a^phi(n) = 1 (mod n)
则可以知道phi©会是方程a^k=1(mod c)的一组解(k=phi©),但是我们并不知道它得到的是否是最小解,因此还需要对它进行约数的枚举,因为phi©和c互质,因此phi©的约数也一定和c互质,因此只要约数分解分解出phi©的最小约数即可得到该方程的最小解
ps:由于欧拉定理要求a和n互质,所以该方程中的10和c也要是互质的,需要判断一下
通过代码:
#include<iostream>
#include<cstring>
#include <cmath>
#include<algorithm>
using namespace std;
typedef long long ll;
ll quick_mul(ll x,ll y,ll p)
{
ll res=0;
while(y){
if(y&1)res=(res+x)%p;
x=(x+x)%p;
y>>=1;
}
return res%p;
}
ll quick_pow(ll x,ll y,ll p)
{
ll res=1;
while(y){
if(y&1)res=quick_mul(res,x,p);//两个longlong类型的数相乘和爆longlong因此需要用到快速乘
x=quick_mul(x,x,p);
y>>=1;
}
return res%p;
}
ll get_eulers(ll n)
{
ll res=n;
for(ll i=2;i<=n/i;i++){
if(n%i==0){
while(n%i==0)n/=i;
res=res/i*(i-1);
}
}
if(n>1)res=res/n*(n-1);
return res;
}
ll gcd(ll a,ll b)
{
return b==0?a:gcd(b,a%b);
}
int main()
{
ll n;
int kase=0;
while(~scanf("%lld",&n)&&n){
ll d=gcd(n,8);
ll c=n/d*9,a=10;
ll phi=get_eulers(c);
ll res=1e18;
if(gcd(a,c)!=1)res=0;//10和c不互质的话不满足条件,此时答案为0
for(ll i=1;i<=phi/i;i++){
if(phi%i==0){
if(quick_pow(a,i,c)==1)res=min(res,i);
if(quick_pow(a,phi/i,c)==1)res=min(res,phi/i);
}
}
printf("Case %d: %lld\n",++kase,res);
}
return 0;
}