题意
给你一个
,让你找到一个只由8组成数字,可以使得
可以整除它。让你输出这个数的最小位数。
思路:
因为
可以用
来表示,其中
为这个数的位数。
所以有
即
令
有
因为 与 互质
所以有
即
令
有
上述模线性方程存在整数解
当且仅当
。
我们要求解位数
,根据如下原根的性质:
对于任意正整数
,如果
,存在最小的正整数
满足
,则有
整除
,因此
整除
。这里的
被称为
模
的阶,记为
。
上述性质可以简单的理解为如果存在解
的话,那么
一定是
的因子。
所以我们可以只需在
的因子中用快速幂检验是否存在解即可。
注意:这里数据范围比较大,直接相乘可能会溢出,所以快速幂要配合着快速乘使用。
#include<iostream>
#include<cstdio>
#include<cmath>
#include<map>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N = 2e6 ;
inline ll fast_mul(ll a, ll b, ll Mod)
{
ll c = a*b-(ll)((long double)a*b/Mod+0.5)*Mod;
return c<0 ? c+Mod : c; //就是算的a*b%Mod;
}
ll Qpow(ll a,ll b,ll p){
ll ans = 1;
a %= p;
while(b){
if(b&1) ans = fast_mul(ans,a,p);
b >>= 1;
a = fast_mul(a,a,p);
}
return ans;
}
ll phi(ll n){
ll ans = n;
for(ll i = 2;i <= sqrt(n);++i){
if(n % i == 0){
ans = ans /i *(i-1);
while(n % i == 0) n /= i;
}
}
if(n > 1) ans = ans /n *(n-1);
return ans;
}
int main(){
ll a;
int p = 0;
while(cin>>a&&a){
++p;
ll d = __gcd(9*a,8LL);
ll k = 9*a/d;
if(__gcd(10LL,k)!=1) printf("Case %d: %lld\n",p,0LL);
else {
ll b = phi(k);
ll ans = (ll)1e11;
for(ll i = 1;i <= sqrt(b);++i){
if(b % i == 0){
if(Qpow(10,i,k) == 1) ans = min(ans,i);
if(Qpow(10,b/i,k) == 1) ans = min(ans,b/i);
}
}
if(ans == (ll)1e11) printf("Case %d: %lld\n",p,0LL);
else printf("Case %d: %lld\n",p,ans);
}
}
}