The Luckiest number HDU - 2462
原题链接
考察:欧拉定理
思路:
已知每个8888...888都可以被表示成:
\[nums = \frac {8\times(10^x-1)}{9}
\]
\[nums \equiv 0 \pmod L
\]
\[(10^x-1)\% \frac{9\times L}{gcd(8,L)}==0
\]
根据欧拉定理,若10与\(\frac{9\times L}{gcd(8,L)}\)互质,则存在最小的正整数x,使得等式成立,而x是\(\frac{9\times L}{gcd(8,L)}\)欧拉函数的约数.
注意那个gcd(9*L,8)也没有关系,9存不存在无所谓,只要与10存在公约数>1即可输出0.
Code
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
typedef long long LL;
LL L;
vector<LL> v;
LL gcd(LL a,LL b)
{
return b?gcd(b,a%b):a;
}
void GetDivide(LL n)
{
v.clear();
for(int i=1;i<=n/i;i++)
{
if(n%i==0)
{
v.push_back(i);
if(i!=n/i) v.push_back(n/i);
}
}
sort(v.begin(),v.end());
}
LL mul(LL a,LL k,LL m)
{
LL res = 0;
while(k)
{
if(k&1) res = (res+a)%m;
a = (a+a)%m;
k>>=1;
}
return res;
}
LL qsm(LL a,LL k,LL m)
{
LL res = 1;
while(k)
{
if(k&1) res = mul(res,a,m);
a = mul(a,a,m);
k>>=1;
}
return res;
}
LL get_er(LL n)
{
LL res = n;
for(LL i=2;i<=n/i;i++)
{
if(n%i==0)
{
res = res/i*(i-1);
while(n%i==0) n/=i;
}
}
if(n>1) res = res/n*(n-1);
return res;
}
int main()
{
int kcase = 0;
while(scanf("%lld",&L)!=EOF&&L)
{
LL s = 9*L/gcd(8,L);
printf("Case %d: ",++kcase);
if(gcd(s,10)>1) {printf("0\n");continue;}
GetDivide(get_er(s));
for(int i=0;i<v.size();i++)
{
LL x = v[i];
if(qsm(10,x,s)==1) {printf("%lld\n",x);break;}
}
}
return 0;
}