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;
    }
    
  • 相关阅读:
    使用 IntraWeb (15)
    使用 IntraWeb (10)
    使用 IntraWeb (8)
    Oralce问题之Oracle ORA-28001:某用户密码过期
    Oralce问题之ORA-12560:TNS协议适配器错误
    JS中数组初始化以及赋值
    EasyUI中取的DataGrid中选中行数据
    反编译DLL并修改DLL中的内容
    在SqlServer和Oralce中创建索引
    SQL中左连接on and条件和where条件执行先后顺序
  • 原文地址:https://www.cnblogs.com/Maxwei-wzj/p/9793673.html
Copyright © 2011-2022 走看看