给一个正整数N,问是否存在N的倍数M,且M的各个位全部由数字8组成,如果存在多个取最小的M;并输出M由几个8组成。
一行,一个整数N
一行一个整数,表示所求的结果
如果无解,输出0
由题得:M==t*N.
由于M==8*11……1,设n==11……1有k位,则n可以表示为:n==10^(k-1)+10^(k-2)+……+10^0.
因为这是一个等比数列,公比q==10,所以根据等比数列求和公式,n==(10^k-1)/9.
带入最开始的式子M==t*N,得到:M==8*n==8*(10^k-1)/9==t*N,移项,得:8*(10^k-1)==9*t*N.
继续化简,由于8和9*t是已知数,所以对它们约分。设d==gcd(8,9*t),则(8/d)*(10^k-1)==(9*t/d)*N.
由于8/d和9*t/d互质,所以(10^k-1)中含因子9*t/d。令m==9*t/d,则(10^k-1)%m==0,所以10^k%m==1,即10^k与m互质.
根据欧拉定理,当a与b互质时,a^phi(b)%b==1.由于10^k%m==1,所以k的一个解就是phi(m).**
幂运算取模有循环节(尽管我并不知道这是为何)。对于10^phi(m)%m==1,设循环节长度为s。显然,10^0%m==1,10^(0+i*s)%m==1即10^(i*s)%m==1。所以,phi(m)==i*s,由于我们实际上不知道s的值,所以问题就变成了求phi(m)内的因数(把phi(m)的因数往式子里面带,找出最小的符合条件的因数)。
1.当数字由若干个重复的数字组成时,可用位数来表示这个数(指数形式)
2.如果(a-1)%p==0,那么a%p==1
3.幂运算取模有循环节;可以通过这一性质对幂运算降幂
#include
#include
#include
#include
#define ll long long
using namespace std;
ll qui(ll a,ll b,ll c){
ll ans=0;
while(b){
if(b&1)ans=(ans+a)%c;
b>>=1,a=(a<<1)%c;
}
return ans;
}
ll getPhi(ll n){
ll ans=n,a=n;
for(ll i=2;i*i<=a;i++)
if(a%i==0){
ans-=ans/i;
while(a%i==0)a/=i;
}
if(a>1)ans-=ans/a;
return ans;
}
ll mont(ll a,ll b,ll c){
ll ans=1;a%=c;
while(b){
if(b&1)ans=qui(ans,a,c);
b>>=1,a=qui(a,a,c);
}
return ans;
}
int main(){
ll n,m,p,pp,ans=2e9+1;scanf("%lld",&n);
m=(9*n)/__gcd(8LL,9*n);
if(__gcd(10LL,m)!=1){printf("0");return 0;}
p=getPhi(m),pp=sqrt(p)+0.5;
for(ll i=1;i<=pp;i++)
if(p%i==0){
if(mont(10,i,m)==1){
printf("%lld",i);
return 0;
}
if(mont(10,p/i,m)==1)ans=min(ans,p/i);
}
printf("%lld",ans);return 0;
}