poj3696 The Luckiest number(欧拉定理)

题意
给你一个 L L ,让你找到一个只由8组成数字,可以使得 L L 可以整除它。让你输出这个数的最小位数。
思路:
因为 888888... 888888... 可以用 1 0 n 1 9 8 \dfrac{10^{n}-1}{9}*8 来表示,其中 n n 为这个数的位数。
所以有

L 1 0 n 1 9 8 L|\dfrac{10^{n}-1}{9}*8

9 L ( 1 0 n 1 ) 8 9*L|(10^{n}-1)*8

d = g c d ( 9 L , 8 ) d=gcd(9*L,8)

9 L d ( 1 0 n 1 ) 8 d \dfrac{9*L}{d}|(10^{n}-1)*\dfrac{8}{d}

因为 9 L d \dfrac{9*L}{d} 8 d \dfrac{8}{d} 互质

所以有

9 L d ( 1 0 n 1 ) \dfrac{9*L}{d} |(10^n-1)

1 0 n 1 ( m o d    9 L d ) 10^n\equiv1(\mod\dfrac{9*L}{d})

k = 9 L d k=\dfrac{9*L}{d}

1 0 n 1 ( m o d    k ) 10^n\equiv1(\mod k)
上述模线性方程存在整数解 n n 当且仅当 g c d ( 10 , k = 1 ) gcd(10,k=1)
我们要求解位数 n n ,根据如下原根的性质:
对于任意正整数 a , m a,m ,如果 ( a , m ) = 1 (a,m) = 1 ,存在最小的正整数 d d 满足 a d 1 ( m o d   m ) a^d≡1(mod \ m) ,则有 d d 整除 φ ( m ) φ(m) ,因此 O r d m ( a ) Ordm(a) 整除 φ ( m ) φ(m) 。这里的 d d 被称为 a a m m 的阶,记为 O r d m ( a ) Ordm(a)
上述性质可以简单的理解为如果存在解 n n 的话,那么 n n 一定是 φ ( k ) φ(k) 的因子。
所以我们可以只需在 φ ( k ) φ(k) 的因子中用快速幂检验是否存在解即可。
注意:这里数据范围比较大,直接相乘可能会溢出,所以快速幂要配合着快速乘使用。
A C   C o d e : AC \ Code:

#include<iostream>
#include<cstdio>
#include<cmath>
#include<map>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N = 2e6 ; 
inline ll fast_mul(ll a, ll b, ll Mod)
{
    ll c = a*b-(ll)((long double)a*b/Mod+0.5)*Mod;
    return c<0 ? c+Mod : c;  //就是算的a*b%Mod;
}
ll Qpow(ll a,ll b,ll p){
    ll ans = 1;
    a %= p;
    while(b){
        if(b&1) ans = fast_mul(ans,a,p);
        b >>= 1;
        a = fast_mul(a,a,p);
    }
    return ans;
}
ll phi(ll n){
    ll ans = n;
    for(ll i = 2;i <= sqrt(n);++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;
}
int main(){
    ll a;
    int p = 0;
    while(cin>>a&&a){
        ++p;
       ll d = __gcd(9*a,8LL);
        ll k = 9*a/d;
        if(__gcd(10LL,k)!=1) printf("Case %d: %lld\n",p,0LL);
        else {
            ll b = phi(k);
            ll ans = (ll)1e11;
            for(ll i = 1;i <= sqrt(b);++i){
                if(b % i == 0){
                    if(Qpow(10,i,k) == 1) ans = min(ans,i);
                    if(Qpow(10,b/i,k) == 1) ans = min(ans,b/i);
                }
            }
            if(ans == (ll)1e11) printf("Case %d: %lld\n",p,0LL);
            else printf("Case %d: %lld\n",p,ans);
        }
    }
}
发布了632 篇原创文章 · 获赞 27 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/qq_43408238/article/details/103995086