| ||||||||||
| Online Judge | Problem Set | Authors | Online Contests | User | ||||||
|---|---|---|---|---|---|---|---|---|---|---|
| Web Board Home Page F.A.Qs Statistical Charts | Current Contest Past Contests Scheduled Contests Award Contest | |||||||||
乘法溢出In Reply To:我的代码,一直WA, 谁给我根绳子上吊吧!!! Posted by:liuyuyangfoam at 2005-12-24 14:47:25 > #include <stdio.h>
> #include <stdlib.h>
> #include <time.h>
> #include <math.h>
>
> bool isPrime(__int64 n);
> bool miller_rabin(__int64 n,int s);
> bool witness(__int64 a,__int64 n);
> __int64 modular_exponentiation(__int64 a,__int64 u,__int64 n);
> void pollard_rho(__int64 n);
> void factorizer(__int64 n); // for n <= 1024*1024
> int binary_length(__int64 x);
> __int64 euclid(__int64 a,__int64 b);
> __int64 euclid_stein(__int64 a,__int64 b);
> __int64 rand64();
>
>
> __int64 min;
>
> int primes[173] = {2, 3, 4, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997, 1009, 1013, 1019, 1021};
>
> int main()
> {
> srand((unsigned)time(NULL));
> int t,i; // the number of test cases, 1 <= t <= 20
> __int64 n;
> scanf("%d",&t);
> for (i=0;i<t;i++) {
> scanf("%I64d",&n);
> if (isPrime(n))
> printf("%s\n","Prime");
> else
> {
> min = n;
> pollard_rho(n);
> printf("%I64d\n",min);
> }
> }
> return 0;
> }
> //////////////////////////////////////////////////////////
> /*
> int main()
> {
> __int64 i=1050028,j,p;
> while(1)
> {
> next:
> i++;
> printf("%I64d\n",i);
> min = i;
> if (isPrime(i))
> {printf("%s\n","Prime");continue; }
> else
> printf("%s\n","Composite");
>
> pollard_rho(i);
> p = min;
> //is prime?
>
> for(j=2;j<=sqrt(i);j++)
> {
> if (i%j==0){
>
> if (j!=p) {printf("pollard WRONG!!!! %I64d j:%I64d p:%I64d\n ",i,j,p);return 1;}
> goto next;
> }
>
> }
> if (!isPrime(i)) {printf("isPrime WRONG!!!! %I64d\n",i);return 1;}
>
>
> }
> return 0;
>
>
> //pollard_rho(4);
> //printf("%I64d\n",min);
> }
> */
> ////////////////////////////////////////////////
> // 2 < N < 2^54
> bool
> isPrime(__int64 n)
> {
> int j;
> if (n==1)
> return false;
> for (j=0;j<173;j++)
> {
> if (n==primes[j]) return true;
> if (n%primes[j]==0) return false; // n is composite.
> }
>
> return miller_rabin(n,50); // s取50应该差不多了
> }
>
> bool
> miller_rabin(__int64 n,int s)
> {
> int j;
> __int64 a;
> for (j=1;j<=s;j++) {
> // Make sure that a is in [ 1, n - 1 ].
> a = rand64()%(n-1)+1;
> if (witness(a,n))
> return false;
> }
> return true;
> }
>
>
> bool
> witness(__int64 a,__int64 n)
> {
> __int64 u=n-1,z=0,j;
> while (u%2==0)
> {
> u=u/2;
> z++;
> }
> __int64 x0 = modular_exponentiation(a,u,n),x1;
> for (j=1;j<=z;j++)
> {
> x1 = x0*x0%n;
> if (x1==1&&x0!=1&&x0!=n-1)
> return true;
> x0=x1;
> }
> if (x1!=1) return true;
> return false;
> }
>
> // a^b mod n, 算法到论 Corollary 31.35
> __int64
> modular_exponentiation(__int64 a,__int64 b,__int64 n)
> {
> __int64 c=0, d=1;
> int i;
> for (i=binary_length(b)-1;i>=0;i--)
> {
> c=c*2;
> d=(d*d)%n;
> if (b&(1<<i))
> {
> c = c + 1;
> d = ( d * a ) % n;
> }
> }
> return d;
> }
>
> // 返回x用二进制表示的长度
> int
> binary_length(__int64 x)
> {
> int result = 0;
> while (x>0)
> {
> x=x>>1;
> }
> return result;
> }
>
> __int64
> rand64()
> {
> __int64 result = 0;
> int i;
>
> for (i=0;i<=62;i++)
> {
> if (rand()%2==0) result = result|1LL<<i;
> }
> result = result|1; // 保证为奇数
> result = result|1LL<<62; // 保证足够的长
> return result;
> }
>
>
> void
> pollard_rho(__int64 n)
> {
> if (n<=1048576/* 1024*1024 */) {factorizer(n);return;}
>
> __int64 i = 1;
> __int64 x1 = rand64() % n;
> __int64 y = x1;
> __int64 d;
> __int64 k = 2;
>
> while(1)
> {
> i++;
> /// printf("n:%I64d x1:%I64d\n",n,x1);
> x1 = (x1 * x1 -1) % n;
> //d = euclid_stein(abs(y-x1), n);
> d = euclid(abs(y-x1), n);
> if (d!=1 && d!=n)
> {
> if (d < min) min = d;
> if (!isPrime(d))
> {
> pollard_rho(d);
> }
> if (n/d < min) min = n/d;
> if (!isPrime(n/d))
> {
> pollard_rho(n/d);
> }
> /// printf("d:%I64d\n",d);
> return;
> }
> if (i==k) {
> y=x1;
> k*=2;
> }
> }
> }
>
>
>
>
> void
> factorizer(__int64 n)
> {
> int j;
> for (j=0;j<173;j++)
> {
> if (n%primes[j]==0) {if (min>primes[j]) min=primes[j];return;}
> }
> }
>
>
> // 欧几里德,求最大公约数
> __int64
> euclid(__int64 a,__int64 b)
> {
> if (b==0) return a;
> else return euclid(b,a%b);
> }
>
>
> /*
> Euclid & stein 算法
> 与传统的Euclid算法不同的是它只有移位和加减法.
> */
> /*
> __int64
> euclid_stein(__int64 a,__int64 b)
> {
> __int64 temp;
> if(a < b) //arrange so that a>b
> {
> temp = a;
> a = b;
> b = temp;
> }
> if ( !b ) // the base case, b == 0
> return a;
> if (((a&1) == 0 ) && ( (b&1) == 0 )) //a and b are even
> return euclid_stein( a>>1, b>>1 )<<1;
> else if ( (b&1) ) // only a is even
> return euclid_stein( a>>1, b );
> else if ( (a&1) ) // only b is even
> return euclid_stein( a, b>>1 );
> else
> return euclid_stein( b, (a-b)>>1 ); // a and b are odd
> }
> */
Followed by:
Post your reply here: |
All Rights Reserved 2003-2013 Ying Fuchen,Xu Pengcheng,Xie Di
Any problem, Please Contact Administrator