• The Luckiest Number ( 欧拉定理变形


    # 题意

    多组测试样例,给定一个L,求位数最少的全由8组成的数是L的倍数,输出时加上"Case t: "

    数据范围:

    1 ≤ L ≤ 2*109

    # 题解

    x位数字每一位是8的数字表示为8*(10x-1)/9

    10x有x+1位,-1为x位由9构成,再除9就是x位由1构成的数字,乘8就是由x位8构成的数字

    即转化成了求最小的x使得

       L|8*(10x-1)/9

    L*k=8*(10x-1)/9

    9*L*k=8*(10x-1)

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

    (9*L)/d * k=8/d*(10x-1)

    u=(9*L)/d ,v=8/d

    u*k=v*(10x-1)

    因为除了最大公约数所以u、v互质

    因为u<v

    u | (10x-1)

    即10x-1 ≡ 0(mod u)

    10x ≡ 1 (mod (9L/d))

    欧拉定理中aφ(n) ≡ 1 (mod n),a和n互质

    所以必定存在一个和10互质的u满足上式

    但是只用欧拉定理无法求出最小的解

    引理:

    正整数a,n互质,则满足a≡ 1 mod( n )的最小正整数x0是φ(n)的约数

    直观上将欧拉定理的φ(n)拆成φ(n) , ax*y≡ 1 mod( n )

    反证法证明:

    将φ(n)拆解成x*k+y,假设x为满足方程最小的值且x>y>0,  x*k <φ(n) ,

    ax*k+y≡ 1 mod( n )

    a≡ 1 mod( n )

    ax*k*ay≡ 1 mod( n )

    ay≡ 1 mod( n )

    那么存在更小的y,矛盾

    最后因为数很大1010*1010 就会爆掉long long,乘法改用龟速乘及时取模防止溢出

    时间复杂度为O(√u) umax=(9*2*109)/d = (1.8 * 1010)/d,d最小为2 约为1010 

     1 #include <bits/stdc++.h>
     2 #define ll long long
     3 using namespace std;
     4 const int N=1e4;
     5 ll L;
     6 int n;
     7 ll gcd(ll a, ll b){return b?(b,a%b):a;}
     8 ll get_phi(ll x){
     9     ll res=x;
    10     for(ll i=2;i*i<=x;i++){
    11         if(x%i==0){
    12             res=res/i*(i-1);
    13             while(x%i==0) x/=i;
    14         }
    15     }
    16     if(x>1) res=res/x*(x-1);
    17     return res;
    18 }
    19 ll qmul(ll a, ll k, ll p){
    20     ll res=0;
    21     while(k){
    22         if(k&1) res=(res+a)%p;
    23         a=(a+a)%p;
    24         k>>=1;
    25     }
    26     return res;
    27 }
    28 ll qmi(ll a,ll k ,ll p){
    29     ll res=1;
    30     while(k){
    31         if(k&1) res=qmul(res,a,p);//会爆long long
    32         a=qmul(a,a,p);//会爆long long
    33         k>>=1;
    34     }
    35     return res;
    36 }
    37 int main(){
    38     while(scanf("%lld",&L),L){
    39             printf("Case %d: ",++n);
    40             ll d=gcd(L,8);
    41             ll u=L/d*9;
    42             if(gcd(u,10)!=1) {printf("0");return 0;}
    43             ll phi=get_phi(u);
    44             ll ans=1e18;
    45             for(ll i=1;i<=phi/i;i++){
    46                 if(phi % i==0){
    47                     if(qmi(10,i,u)==1) ans=min(ans,i);
    48                     if(qmi(10,phi/i,u)==1) ans=min(ans,phi/i);
    49                 }
    50             }
    51             printf("%lld
    ",ans);
    52     }
    53 }
  • 相关阅读:
    inflate
    【Android布局】在程序中设置android:gravity 和 android:layout_Gravity属性
    安卓延时执行代码
    Listview控件
    安卓的progress
    android studio的弹出层
    解决mysql的日志文件过大的问题
    linux查文件大小
    乔坟往事-姑妄言之
    乔坟往事-村里人家
  • 原文地址:https://www.cnblogs.com/hhyx/p/12640087.html
Copyright © 2020-2023  润新知