POJ 3358 Period of an Infinite Binary Expansion 歐拉函數+歐拉定理

來源:互聯網
上載者:User

題意:輸入一個有理數p/q(保證是一個小數),然後將其小數部分用二進位表示。求出在此種表示下的迴圈起點和迴圈節長度

{x} = 0.a1a2...ar(ar+1ar+2...ar+s)w

題解:來自Discuss

我們可以觀察一下1/10這組資料,按照二進位轉換法(乘二法),我們可以得到:
1/10  2/10 4/10 8/10 16/10 32/10 ...
然後都分子都儘可能減去10,得到:
1/10  2/10 4/10 8/10 6/10 2/10 ...
這時候,發現出現了重複,那麼這個重複就是我們要求的最小迴圈。
抽象出模型如下:對p/q
首先p'=p/gcd(p,q)
q'=q/gcd(p,q);

然後我們就是求p'*2^i == p'*2^j (mod q')   (“==”表示同餘,i<j)
經過變換得到:
p'*2^i*(2^(j-i)-1) ==0 (mod q')
也就是 q' | p'*2^i*(2^(j-i)-1)
由於gcd(p',q')=1,
得到: q' | 2^i*(2^(j-i)-1)
因為2^(j-i)-1為奇數,所以q'有多少個2的冪,i就是多少,而且i就是迴圈開始位置的前一位。
那麼令q''為q'除去2的冪之後的數
此時 q'' | 2^(j-i)-1
也就是求出x,使得 2^x ==1 (mod q'')    

歐拉定理:若a與p互質,則a^Φ(p) == 1 (modp)

所以2^x ==1 (mod q'')   必定存在解。

現在我要求的是最小迴圈節。又已知,若a,p互質,且a^x == 1 (mod p), 那麼必定有a | Φ(p)。

至此,只需要從小到大枚舉Φ(p)的因子即可。

 

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;__int64 fact[100000], pf;__int64 Euler ( __int64 n ){    __int64 ret = n, i;    for ( i = 2; i * i <= n; i++ )    {        if ( n % i == 0 )        {            n /= i;            ret = ret - ret / i;            while ( n % i == 0 )                n /= i;        }    }    if ( n > 1 )        ret = ret - ret / n;    return ret;}__int64 gcd ( __int64 a, __int64 b ){    __int64 c;    while ( b != 0 )    {        c = a % b;        a = b;        b = c;    }    return a;}__int64 mod_mult ( __int64 a, __int64 b, __int64 n ){    __int64 ret = 0;    a = a % n;    while ( b >= 1 )    {        if ( b & 1 )        {            ret += a;            if ( ret >= n ) ret -= n;        }        a <<= 1;        if ( a >= n ) a -= n;        b >>= 1;    }    return ret;}__int64 mod_exp ( __int64 a, __int64 b, __int64 n ){    __int64 ret = 1;    a = a % n;    while ( b >= 1 )    {        if ( b & 1 )            ret = mod_mult(ret,a,n);        a = mod_mult(a,a,n);        b >>= 1;    }    return ret;}void factor ( __int64 x ){    pf = 0;    for ( __int64 i = 2; i * i <= x; i++ )        if ( x % i == 0 )            fact[pf++] = i, fact[pf++] = x / i;}int main(){    __int64 eul;    __int64 p, q, d, cnt, cs = 0;    while ( scanf("%I64d/%I64d",&p,&q) != EOF )    {        if(!p){ printf("Case #%I64d: 1,1 \n",++cs);continue; }        d = gcd(p,q);        p /= d; q /= d;        cnt = 1;        while ( q % 2 == 0 ) { q >>= 1; cnt++; }        eul = Euler(q);        factor(eul);        sort(fact,fact+pf);        fact[pf++] = eul; __int64 i;        for ( i = 0; i < pf; i++ )            if ( mod_exp (2, fact[i], q) == 1 ) break;        printf("Case #%I64d: %I64d,%I64d\n",++cs,cnt,fact[i]);    }    return 0;}

 

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.