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;
}
posted @ 2021-06-03 10:24  acmloser  阅读(27)  评论(0编辑  收藏  举报