码迷,mamicode.com
首页 > 其他好文 > 详细

HDU 2462 The Luckiest number

时间:2015-08-17 23:42:27      阅读:131      评论:0      收藏:0      [点我收藏+]

标签:gcd   算法   

传送门
题目大意:
定义只含有数字8的数为幸运数
给定正整数L,求L的所有倍数中最小的幸运数
算法思路:
设最终答案为x个8,则x满足(10x-1)*8/9≡0 (mod L)
化简:10x≡1 (mod n),其中n=9L/gcd(9L,8)
这是一个离散对数的问题,求解方法如下:
若gcd(10,n)>1,无解
若gcd(10,n)=1,由欧拉定理:10?(n)≡1 (mod n)。可以证明,x为?(n)的约数,从小到大枚举约数即可
10l≡1 (mod n) 则成立的最小 l 是? (n)的约数 这个性质竞赛中经常用到

#include <bits/stdc++.h>
using namespace std;
#define prt(k) cerr<<#k" = "<<k<<endl
typedef long long ll;
typedef long long LL;
const ll inf = 0x3f3f3f3f;
ll gcd(ll a, ll b)
{
    return b==0 ? a: gcd(b, a%b);
}

ll L;
ll mul(ll a, ll b, ll mod)
{
    ll ret = 0;
    for (; b; b>>=1, a=(a+a)%mod) if (b &1)
    {
        ret = (ret + a) % mod;
    }
    return ret;
}
ll pmod(ll a, ll n, ll mod)
{
    ll r = 1;
    for (; n>0; a=mul(a,a,mod), n>>=1)
        if (n & 1)
        r  = mul(r, a, mod);
    return r;
}
ll phi(ll n)
{
    ll m = sqrt(n + 0.5);
    ll ans = n;
    for (int i=2;i<=m;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;
}
bool can(ll x)
{
    return pmod(10, x, L) == 1;
}
int main()
{
    int ca = 1;
    while (cin>>L && L) {
        ll m = L;
        L = 9 * L / gcd(8, 9*L);
        printf("Case %d: ", ca++);
        if (gcd(10, L) > 1) {
            puts("0");
            continue;
        }
        ll n = phi(L);
        ll ans = 1e18;
        for (ll i = 1; i <= sqrt(n+0.5); i++) if (n%i==0)
        {
            if (can(i)) ans = min(ans, i);
            if (can(n / i)) ans = min(ans, n / i);
        }
        printf("%I64d\n", ans>=1e18 ? 0 : ans);
    }
    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

HDU 2462 The Luckiest number

标签:gcd   算法   

原文地址:http://blog.csdn.net/oilover/article/details/47733691

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!