zoukankan      html  css  js  c++  java
  • 【POJ3696】The Luckiest Number-欧拉定理+快速幂

    测试地址:The Luckiest Number
    题目大意:给出一个正整数L(2,000,000,000),要使正整数888...8��K能整除L,求最小的K,如果不存在这样的K则输出0。
    做法:这题的思路很神……没看题解的时候根本不知道怎么做,调也调了好一会,我好弱啊……
    这一题需要使用欧拉定理+快速幂来解决。
    我们发现999...9��K可以表示为10K1,所以888...8��K可以表示为8/9×(10K1),那么存在一个整数p使得8/9×(10K1)=L×p,所以10K1=9/8×L×p。由于等式右边要是整数,那么p应该满足8|(L×p)。因为L已经包含gcd(L,8)这些因子,所以p需要包含8/gcd(L,8)这些因子,所以可以将p写成p=8/gcd(L,8)×p1。将其代入前面的式子,可以得到10K1=9×L/gcd(L,8)×p1,设m=9×L/gcd(L,8),则原式可以写成10K1=m×p1,这样我们就把问题转化成了求同余方程10K1(modm)的最小的正整数解。根据欧拉定理,可以得到10φ(m)1(modm),可以证明如果K是一个小于φ(m)的解,那么K|φ(m)。那么我们就可以按照下列步骤完成这一题:
    1.求出mφ(m)φ(m)的所有质因子。这一步可以用O(N)的试除法来做。
    2.令x=φ(m),对于φ(m)的每一个质因子pi,判断10x/pi%m是否等于1,如果等于则令x=x/pi,否则跳过。由于指数很大,需要使用快速幂来算出结果,而因为数字直接乘起来可能会溢出,要用快速乘代替乘法。
    3.对所有质因子进行以上操作后,最后的x就是最小的K
    那么无解的情况呢?显然可知,如果gcd(10,m)1,那么上面的同余方程就无解。这样我们就完美解决了这一题。
    犯二的地方:试除法忘记探测最后剩余是不是1了,导致可能漏掉一个质因子,以后要注意……
    以下是本人代码:

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #define ll long long
    using namespace std;
    ll L,fac[1010]={0};
    
    ll gcd(ll a,ll b)
    {
      return (b==0)?a:gcd(b,a%b);
    }
    
    ll phi(ll x)
    {
      ll p=x,s=x;
      for(ll i=2;i*i<=s;i++)
        if (!(x%i))
        {
          p=p/i*(i-1);
          while(!(x%i)) x/=i;
        }
      if (x>1) p=p/x*(x-1);
      return p;
    }
    
    void find_factor(ll x)
    {
      ll s=x;
      fac[0]=0;
      for(ll i=2;i*i<=s;i++)
        if (!(x%i))
        {
          fac[++fac[0]]=i;
          while(!(x%i)) x/=i;
        }
      if (x>1) fac[++fac[0]]=x;
    }
    
    ll mult(ll a,ll b,ll mod)
    {
      a%=mod,b%=mod;
      ll s=a,sum=0;
      while(b)
      {
        if (b&1)
        {
          sum+=s;
          if (sum>=mod) sum-=mod;
        }
        b>>=1;
        s<<=1;
        if (s>=mod) s-=mod;
      }
      return sum;
    }
    
    ll power(ll a,ll b,ll mod)
    {
      ll s=a,sum=1;
      while(b)
      {
        if (b&1) sum=mult(sum,s,mod);
        b>>=1;s=mult(s,s,mod);
      }
      return sum;
    }
    
    int main()
    {
      int t=0;
      while(scanf("%lld",&L)&&L)
      {
        t++;
        ll m=L/gcd(L,8)*9,p=phi(m),x=p;
        if (gcd(m,10)!=1) {printf("Case %d: 0
    ",t);continue;}
        find_factor(p);
        for(int i=1;i<=fac[0];i++)
        {
          while(1)
          {
            x/=fac[i];
            if (power(10,x,m)!=1)
            {
              x*=fac[i];
              break;
            }
            else if (x%fac[i]) break;
          }
        }
        printf("Case %d: %lld
    ",t,x);
      }
    
      return 0;
    }
    
  • 相关阅读:
    leetcode Convert Sorted List to Binary Search Tree
    leetcode Convert Sorted Array to Binary Search Tree
    leetcode Binary Tree Level Order Traversal II
    leetcode Construct Binary Tree from Preorder and Inorder Traversal
    leetcode[105] Construct Binary Tree from Inorder and Postorder Traversal
    证明中序遍历O(n)
    leetcode Maximum Depth of Binary Tree
    限制 button 在 3 秒内不可重复点击
    HTML 和 CSS 画三角形和画多边行基本原理及实践
    在线前端 JS 或 HTML 或 CSS 编写 Demo 处 JSbin 与 jsFiddle 比较
  • 原文地址:https://www.cnblogs.com/Maxwei-wzj/p/9793673.html
Copyright © 2011-2022 走看看