zoukankan      html  css  js  c++  java
  • poj3696 快速幂的优化+欧拉函数+gcd的优化+互质

    这题满满的黑科技orz

    题意:给出L,要求求出最小的全部由8组成的数(eg: 8,88,888,8888,88888,.......),且这个数是L的倍数

    sol:全部由8组成的数可以这样表示:((10^x)-1)*(8/9)

    那么有m=((10^x)-1)*(8/9)=k*L,answer即满足条件的最小的x

    性质1:若ax=by且a和b互质,那么说明a中没有任何b的质因子,b的质因子一定在x里。所以x是b的倍数。

    所以先想方设法在等式中构造两个互质的数以便化简。我们取p=8/gcd(8,L),q=9*L/gcd(8,L)

    那么有p*((10^x)-1)=q*k,且p与q互质【8/gcd(8,L)与L/gcd(8,L)一定互质。8又没有3这个质因子,所以9*L/gcd(8,L)还是会互质】

    所以由性质1,(10^x)-1是q的倍数。

    所以(10^x)-1=0  (mod q)

      (10^x)=1  (mod q)

    性质2:欧拉定理。对于正整数a,n,若gcd(a,q)=1,则有a^phi(q)=1  (mod q)    【其中phi是欧拉函数】

    这个式子是不是和上面很像呢~

    所以若gcd(10,q)=1说明有解,否则无解

    对于有解的情况,x=phi(q)就是一个解,但不一定是最小解。actually,0---phi(q)中还可能存在解。

    性质3:因为后面有mod n,而余数都是有循环节的。(即一个循环周期的长度,设为r)

    eg:如果有10^a=1  (mod q),那么10^(a+r)=1  (mod q)

    首先x=0是一个解【10^0=1  (mod q)】。而且已经确定phi(q)也是一个解了。所以phi(q)一定是这个循环节r的倍数。

    根据性质3,r肯定也是一个解。而且是最小的。

    所以只要枚举phi(q)的约数,找出其中最小的满足条件的即可。

    -----------------------接下来是满满的黑科技orz----------------------

    Q1:本题数据很大,求gcd的过程会TLE肿么办

    A1:因为gcd里面有一个数字是固定的,所以可以用一下黑科技

            //q=9*N/gcd(8,N);
            q=9*N;
            for (int i=0;i<3;i++)
                if (q%2==0)
                    q=q/2;
                else break;
    要求的是q/gcd(8,N)
    而8分解质因数之后是2^3,也就是说带8的gcd里面最多也只可能有3个2。所以直接把这3个2能除掉的都除掉就行了
            //if (gcd(10,q)!=1)    ans=0;
            if  ((q%2==0)||(q%5==0))
                ans=0;
    10的质因子只有2和5。如果q是2或5的倍数,就说明q和10不互质。

    Q2:求快速幂取模(10^x)%q的时候,数据超了long long的范围,会出错

    A2:这样:

    LL func(LL a,LL b,LL c)     //a*b%c
    {
        long long ret = 0;
        while (b)
        {
            if (b & 1)
                ret = (ret + a) % c;
            a = 2 * a % c;
            b >>= 1;
        }
        return ret;
    }
    
    LL pow_mod(LL a,LL b,LL MOD)
    {
        if (a==1)   return 1;
        LL t=a%MOD,ans=1;
        while(b)
        {
            if (b&1)
                ans=func(ans,t,MOD);
            t=func(t,t,MOD);
            b>>=1;
        }
        return ans;
    }

    其实我也没看懂func是个什么鬼。。。。【逃

    AC Code:

      1 #include <iostream>
      2 #include <cstdio>
      3 using namespace std;
      4 #define LL long long
      5 #define MAXL 1000
      6 
      7 LL TC=0;
      8 LL N,MOD,TM,q,ans;
      9 int phi[MAXL+5];
     10 
     11 int gcd(int a,int b)                   //辗转相除法,返回gcd(a,b)
     12 {
     13     if (b==0) return a;
     14     return gcd(b,a%b);
     15 }
     16 
     17 long long euler(long long n)
     18 {
     19     long long ret = n;
     20     for (long long i = 2; i * i <= n; i++)
     21         if (n % i == 0)
     22         {
     23             ret = ret / i * (i - 1);
     24             while (n % i == 0)
     25                 n /= i;
     26         }
     27     if (n > 1)
     28         ret = ret / n * (n - 1);
     29     return ret;
     30 }
     31 
     32 
     33 /*
     34 LL pow_mod(LL a,LL b,LL MOD)
     35 {
     36     if (a==1)   return 1;
     37     LL t=a%MOD,ans=1;
     38     while(b)
     39     {
     40         if (b&1)
     41             ans=ans*t%MOD;
     42         t=t*t%MOD;
     43         b>>=1;
     44     }
     45     return ans;
     46 }
     47 */
     48 
     49 LL func(LL a,LL b,LL c)     //a*b%c
     50 {
     51     long long ret = 0;
     52     while (b)
     53     {
     54         if (b & 1)
     55             ret = (ret + a) % c;
     56         a = 2 * a % c;
     57         b >>= 1;
     58     }
     59     return ret;
     60 }
     61 
     62 LL pow_mod(LL a,LL b,LL MOD)
     63 {
     64     if (a==1)   return 1;
     65     LL t=a%MOD,ans=1;
     66     while(b)
     67     {
     68         if (b&1)
     69             ans=func(ans,t,MOD);
     70         t=func(t,t,MOD);
     71         b>>=1;
     72     }
     73     return ans;
     74 }
     75 
     76 int main()
     77 {
     78     //calc_phi(MAXL);
     79     while (~scanf("%I64d",&N))
     80     {
     81         TC++;
     82         if (N==0)   break;
     83         //q=9*N/gcd(8,N);
     84         q=9*N;
     85         for (int i=0;i<3;i++)
     86             if (q%2==0)
     87                 q=q/2;
     88             else break;
     89 
     90         TM=euler(q);    //tm=phi[q];
     91         ans=TM;
     92         //if (gcd(10,q)!=1)
     93         if  ((q%2==0)||(q%5==0))
     94             ans=0;
     95         else
     96         {
     97             for (LL i=1; i*i<=TM; i++)
     98                 if (TM%i==0)
     99                 {
    100                     LL t1=i,t2=TM/i;
    101                     LL M1=pow_mod(10,t1,q);
    102                     LL M2=pow_mod(10,t2,q);
    103                     //cout<<t1<<" "<<M1<<endl<<t2<<" "<<M2<<endl;
    104                     if ((M1==1)&&(t1<ans))
    105                         ans=t1;
    106                     if ((M2==1)&&(t2<ans))
    107                         ans=t2;
    108                 }
    109         }
    110         printf("Case %d: ",TC);
    111         cout<<ans<<endl;
    112     }
    113 }
    114 
    115 
    116 
    117 /*
    118 LL len,tmp,N;
    119 int TC=0;
    120 bool ok;
    121 
    122 int main()
    123 {
    124     while(~scanf("%I64d",&N))
    125     {
    126         TC++;
    127         if (N==0)   break;
    128         tmp=8;
    129         len=1;
    130         ok=false;
    131         if (tmp%N==0)   ok=true;
    132         while ((!ok)&&(len<=MAXL))
    133         {
    134             tmp=tmp*10+8;
    135             len++;
    136             if (tmp%N==0)
    137                 ok=true;
    138         }
    139         if (ok)
    140             printf("Case %d: %I64d
    ",TC,len);
    141         else
    142             printf("Case %d: 0
    ",TC);
    143     }
    144 
    145     return 0;
    146 }
    147 */
    View Code

    Reference:

    http://www.cnblogs.com/rainydays/archive/2012/11/05/2754760.html

    http://blog.csdn.net/yhrun/article/details/6908470

  • 相关阅读:
    HDU 1102 Constructing Roads
    HDU 1285 确定比赛名次。
    最小生成树 HDU 各种畅通工程的题,prim和kru的模板题
    HDU Jungle Roads 1301 最小生成树、
    并查集小结(转)
    HDU hdu 2094 产生冠军 拓扑排序 判定环
    模运算(转)
    拓扑排序(主要是确定环和加法) HDU 2647 Reward
    HDU 1372 Knight Moves 简单BFS
    用计算机模型浅析人与人之间沟通方式 (一)如何谈话
  • 原文地址:https://www.cnblogs.com/pdev/p/4316596.html
Copyright © 2011-2022 走看看