最幸运的数字

题目链接

题意:给一个数L,问至少多少个8连在一起组成的正整数是L的倍数。

思路:x个8一起组成的正整数可表示为8*(10^x-1)/9。然后满足L|8*(10^x-1)/9。等价于10^x=1(mod9*L/d),d=gcd(L,8)。

所以我们只需要枚举phi[9*L/d]的约数就行了,看能否满足。满足的那个约数就是答案。前提是10与9*L/d互质。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
#include<queue>
#include<cmath>
#define ll long long
using namespace std;
ll n;
ll f[100010];
ll gcd(ll a, ll b)
{
    return b?gcd(b,a%b):a;
}
ll eler(ll m)
{
    ll res=m;
    for(ll i=2;i*i<=m;i++)
    {
        if (m%i==0)
            res=res/i*(i-1);
        while(m%i==0)
            m/=i;
    }
    if(m>1)
        res=res/m*(m-1);
    return res;
}
void find(ll x)
{
  ll s=x;
  f[0]=0;
  for(ll i=2;i*i<=s;i++)
    if (!(x%i))
    {
      f[++f[0]]=i;
      while(!(x%i))
      x/=i;
    }
  if(x>1)
  f[++f[0]]=x;
}
bool check(ll x,ll mod)
{
    ll res=1;
    ll h=10;
    while(x)
    {
        if(x&1)
        res=(res*h)%mod;
        h=(h*h)%mod;
        x>>=1;
    }
    return (res%mod)==1;
}
int main()
{
    int k=0;
    while(~scanf("%lld",&n))
    {
        if(n==0)
        break;
        ll d=gcd(n,8ll);
        ll m=eler(9*n/d);
        ll p=9*n/d;
        if(gcd(p,10ll)!=1){
        printf("Case %d: %lld\n",++k,0ll);
        continue;
    }
        find(m);
    //    printf("m:%lld\n",m);
    //    printf("p:%lld\n",p);
        for(ll i=1;i<=f[0];i++)
        {
        //    printf("f:%d\n",f[i]);
            while(1)
            {
                m/=f[i];
                if(!check(m,p))
                {
                    m*=f[i];
                    break;
                }
                else
                {
                    if(m%f[i])
                    {
                        break;
                    }
                }
            }
        }
        printf("Case %d: %lld\n",++k,m);
    }
 } 

 

posted @ 2019-08-05 20:59  Ldler  Views(359)  Comments(0Edit  收藏  举报