POJ_3696 The Luckiest number 【欧拉定理+同余式+对取模的理解】

一、题目

Chinese people think of ‘8‘ as the lucky digit. Bob also likes digit ‘8‘. Moreover, Bob has his own lucky number L. Now he wants to construct his luckiest number which is the minimum among all positive integers that are a multiple of L and consist of only digit ‘8‘.

Input

The input consists of multiple test cases. Each test case contains exactly one line containing L(1 ≤ L ≤ 2,000,000,000).

The last test case is followed by a line containing a zero.

Output

For each test case, print a line containing the test case number( beginning with 1) followed by a integer which is the length of Bob‘s luckiest number. If Bob can‘t construct his luckiest number, print a zero.

Sample Input

8
11
16
0

Sample Output

Case 1: 1
Case 2: 2
Case 3: 0

二、题意分析

1.首先要根据题意写出一个公式

有了这个公式,我们就可以进行下一步

这样,得出,其中P其实可以发现是可以变为任意大小的整数的,所以直接不用管

这个公式再联系同余式

变形

行吧,不服不行,这里我们也应该非常清楚,该同余方程有解的充分必要条件是gcd(10^x,M) = 1.根据大整数的素数分解,10的素因子只有2,5,所以进一步推出有解的条件为gcd(10,M)=1.

那么我们其实已经分析出了没有x的条件就是gcd(10,M)!=1.

此处结合

欧拉定理:对任何两个互质的正整数a,m(m≥2)有a^φ(m)≡1(mod m).

那么我们也可以得出,当gcd(10,M)=1时,有

推到这里挺不容易的,但更加不幸的是,这并不意味着我们就成功了 - -!

我们要找的是最小的x。这里我们需要知道指数的mod运算是有循环节的。我们假设上面这个欧拉定理公式的循环节长度是r。那么可以推出

再结合一个常识式子

OK,再开动我们的小脑筋,这不就是让我们求满足

算你狠~

接下来就是在M的欧拉函数值的所有因子F中,找到满足上面10^F≡1(mod M)的最小因子F,你就成功了!

对于代码写法,我是先线性打sqrt(MAX)的素数表,然后再算欧拉函数值。时间250ms(我绝对不是二百五..)。

三、AC代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
const int MAXN = 1e5+3;
bool isPrime[MAXN];
int Prime[MAXN], nPrime;
LL Factor[MAXN], Cnt;

LL Multi(LL a, LL b, LL mod)
{
    LL ans = 0;
    while(b)
    {
        if(b&1)
        {
            ans = (ans + a)%mod;
        }
        b>>=1;
        a = (a+a)%mod;
    }
    return ans;
}

LL Pow(LL a, LL n, LL mod)
{
    LL ans = 1;
    while(n)
    {
        if(n&1)
        {
            ans = Multi(ans, a, mod);
        }
        n>>=1;
        a = Multi(a, a, mod);
    }
    return ans;
}

LL gcd(LL a, LL b)
{
    return b==0?a:gcd(b, a%b);
}

void getPrime() //线筛素数
{
    memset(isPrime, 1, sizeof(isPrime));
    isPrime[0] = isPrime[1] = 0;
    nPrime = 0;
    for(int i = 2; i < MAXN; i++)
    {
        if(isPrime[i])
        {
            Prime[nPrime++] = i;
        }
        for(int j = 0; j < nPrime && (LL)i*Prime[j] < MAXN ; j++)
        {
            isPrime[ i*Prime[j] ] = 0;
            if(i%Prime[j])
                break;
        }
    }
}

LL Euler(LL N)
{
    LL Phi = N;
    for(int i = 0; Prime[i]*Prime[i] <= N; i++)
    {
        if(N%Prime[i] == 0)
        {
            Phi = Phi - Phi/Prime[i];
            do
            {
                N/=Prime[i];
            }while(N%Prime[i] == 0);
        }
    }
    if(N>1)
        Phi = Phi - Phi/N;
    return Phi;
}

LL solve(LL N)
{
    LL M = N/gcd(N, 8)*9;
    if(gcd(10, M) != 1)
    {
        return 0;
    }
    LL Phi = Euler(M);
    Cnt = 0;
    for(LL i = 1; i*i < Phi; i++)
    {
        if(Phi%i == 0)
        {
            Factor[Cnt++] = i;
            Factor[Cnt++] = Phi/i;
        }
    }
    sort(Factor, Factor+Cnt);
    for(LL i = 0; i < Cnt; i++)
    {
        if(Pow(10, Factor[i], M) == 1)
            return Factor[i];
    }
    return 0;
}

int main()
{
    LL N;
    int cnt = 0;
    getPrime();
    while(scanf("%I64d", &N) && N)
    {
        cnt++;
        printf("Case %d: %I64d\n", cnt, solve(N));
    }
    return 0;
}

  

原文地址:https://www.cnblogs.com/dybala21/p/9749791.html

时间: 2024-10-15 23:56:37

POJ_3696 The Luckiest number 【欧拉定理+同余式+对取模的理解】的相关文章

Big Number(大整数取模)

Big Number Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 4789    Accepted Submission(s): 3329 Problem Description As we know, Big Number is always troublesome. But it's really important in ou

hdu 5109(构造数+对取模的理解程度)

Alexandra and A*B Problem Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 802    Accepted Submission(s): 211 Problem Description Alexandra has a little brother. He is new to programming. One day

POJ3696 The Luckiest Number 欧拉定理

昨天终于把欧拉定理的证明看明白了...于是兴冲冲地写了2道题,发现自己啥都不会qwq 题意:给定一个正整数L<=2E+9,求至少多少个8连在一起组成正整数是L的倍数. 这很有意思么... 首先,连续的8可表示为:8*(10^x-1)/9; 那么就是L|8*(10^x-1)*9 => 9*L|8*(10^x-1) ,求最小的x: 我们设d=gcd(L,8) 则9*L/d | 8/d*(10^x-1),因为此时9*L/d 和 8/d 互质,所以9*L/d | 10^x-1,所以 10^x ≡ 1

BZOJ 3884 欧拉定理 无穷幂取模

详见PoPoQQQ的博客.. 1 2 #include <iostream> 3 #include <cstring> 4 #include <cstdio> 5 #include <algorithm> 6 #define LL long long 7 using namespace std; 8 LL KASE,p; 9 inline LL Get_Phi(LL x) 10 { 11 LL Ret=x; 12 for (LL i=2;i*i<=x;

快速幂取模的理解

快速幂的优越性(欢迎大家在此评论并提出您宝贵的建议) 常用公式: ( a + b  ) % c =  ( a % c + b% c ) % c                                         ( a * b  ) % c  =  ( a % c * b% c ) % c 1:削减运算步骤,避免 如计算,a=2,b=10; 可以转换为   (a*a)的4次方   *   a的平方: 具体转换步骤如右:        由于b/2有小数丢失,故y存在(当b为偶数时,y=

The Luckiest number(hdu2462)

The Luckiest number Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1163    Accepted Submission(s): 363 Problem Description Chinese people think of '8' as the lucky digit. Bob also likes digit '

poj_3696_The Luckiest number

Chinese people think of '8' as the lucky digit. Bob also likes digit '8'. Moreover, Bob has his own lucky number L. Now he wants to construct his luckiest number which is the minimum among all positive integers that are a multiple of L and consist of

poj-3696 The Luckiest number

题意: 给出一个数L,求一个最小的x,使长度为x的888...8这个数整除L: 无解输出0,L<=2*10^9: 题解: 即求满足下式的最小x值: 8/9*(10^x-1)==k*L         (k为正整数) 8*(10^x-1)==k*9*L 为继续化简,求出r=gcd(L,8): 8/r *(10^x-1)==k*9*L/r 因为8/r与9*L/r互质,9*L这个因式必在(10^x-1)中,所以原式即为: 10^x-1≡0(mod 9*L/r) 10^x≡1(mod 9*L/r) 设q

HDU 1212 Big Number(C++ 大数取模)(java 大数类运用)

Big Number 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1212 --每天在线,欢迎留言谈论. 题目大意: 给你两个数 n1,n2.其中n1 很大很大,n1%n2的值. 知识点: ①秦九韶公式:例:1314= ((1*10+3)*10+1)*10+4 ②(a*b)%c == (a%c)*(b%c) .(a+b)%c == (a%c)+(b%c) . 思路: 每步取模即可. C++ AC代码: 1 #include <iostream>