POJ 3358 Period of an Infinite Binary Expansion ★ (数论好题:欧拉函数)
生活随笔
收集整理的這篇文章主要介紹了
POJ 3358 Period of an Infinite Binary Expansion ★ (数论好题:欧拉函数)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題目鏈接:http://poj.org/problem?id=3358 題目大意:給定一個真分數p/q,求出在此種表示下的循環起點和循環節長度:{x} = 0.a1a2...ar(ar+1ar+2...ar+s)w ? 我們可以觀察一下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,我們先把它化成最簡真分數,即gcd(p,q)=1. 那么我們就是要找p*2^i = p*2^j (mod q),這樣就找到了循環節. 因為gcd(p,q)==1,所以可以化簡模方程得:2^i*(2^(j-i)-1) = 0 (mod q) 因為2^(j-i)-1是個奇數,所以i = (q的因子中2的個數). 得q' = q / 2^i . 那么此時就剩下2^(j-1) = 1 (mod q'),并且j-i就是循環節長度,我們記為len. 因為gcd(2, q') == 1,所以由費馬小定理的歐拉推廣可知,2^Φ(i) = 1 (mod q'),所以一定有解。而且由定理可知:若a,p互質,且a^x = 1 (mod p), 那么必定有x | Φ(p). 所以最后枚舉phi(i)的因子即可. ?
#include
#include
#include
using namespace std;
long long gcd(long long a, long long b){return b ? gcd(b, a%b) : a;
}
long long phi(long long n){long long res = n;for (int i = 2; i * i <= n; i ++){if (n % i == 0){res = res / i * (i - 1);while(n % i == 0)n /= i;}}if (n > 1){res = res / n * (n - 1);}return res;
}
unsigned long long quick_add_mod(unsigned long long a, unsigned long long b, unsigned long long m){unsigned long long res = 0, tmp = a % m;while(b){if (b & 1){res = res + tmp;res = (res >= m ? res - m : res); //用減法比用mod快}b >>= 1;tmp <<= 1;tmp = (tmp >= m ? tmp - m : tmp);}return res;
}long long exp_mod(long long a, long long b, long long m){long long res = 1 % m, tmp = a % m;while(b){if (b & 1){res = quick_add_mod(res, tmp, m);}tmp = quick_add_mod(tmp, tmp, m);b >>= 1;}return res;
}
vector factor;
void Factor(long long n){factor.clear();factor.push_back(1);factor.push_back(n);for (int i = 2; i * i <= n; i ++){if (n % i == 0){factor.push_back(i);factor.push_back(n / i);}}
}
int main(){long long p, q, caseo = 1;while(scanf("%I64d%*c%I64d", &p, &q) == 2){//化成最簡分數long long tmp_g = gcd(p, q);p /= tmp_g;q /= tmp_g;long long first_bit = 1;long long tmp_q = q;while(tmp_q % 2 == 0){first_bit ++;tmp_q >>= 1;}long long length = 0;Factor(phi(tmp_q));vector :: iterator it = factor.begin();sort(it, it+factor.size());for (size_t i = 0; i < factor.size(); i ++){//printf("%d\n", factor[i]);if (exp_mod(2, factor[i], tmp_q) == 1){length = factor[i];break;}}printf("Case #%I64d: %I64d,%I64d\n", caseo ++, first_bit, length);}return 0;
}
?
轉載于:https://www.cnblogs.com/AbandonZHANG/archive/2013/01/22/4113986.html
總結
以上是生活随笔為你收集整理的POJ 3358 Period of an Infinite Binary Expansion ★ (数论好题:欧拉函数)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 转:C#动态循环生成button怎么分别
- 下一篇: java byte 循环左移 循环右移