第16章 数论问题 if(!(n&1))return 0; u64 k = 0, i, j, m, a; m = n - 1;
while(m%2==0)m=(m>>1),k++; for(i=0;i a = square_multiply(random()%(n-1)+1, m, n);//平方乘 if(a==1)continue; for(j=0;j if(j return 1; } //Pollard p,只找出一个因子。 u64 gcd(u64 a,u64 b){ if(b==0) return a; else return gcd(b,a%b); } //用公式f(x) = x^2 + 1检验碰撞。 u64 f(u64 x, u64 n ){ return (by(x,x,n)+1)%n; } //分解不到,return 0 u64 Pollard(u64 n){ if(n<=2)return 0; if(!(n&1))return 2; //必不可少 u64 i, p, x,xx; for(i=1;i xx = f(x,n); p = gcd( (xx+n-x)%n , n); while(p==1){ x = f(x,n); xx = f( f(xx,n),n); p = gcd( (xx+n-x)%n,n)%n; } if(p)return p; } return 0; } 243· · ACM程序设计培训教程 u64 prime(u64 a){ if(Miller_Rabin(a))return 0; u64 t = Pollard(a), p,d;d=a/t;if(d int main(){ u64 l, a, t; limit = 1; limit = limit<<63; //动态化分段使用 scanf(\ while(t--){scanf(\ if(Miller_Rabin(a))printf(\ else printf(\ } return 0; } 16.4 其他—Pell方程 16.4.1 〖案例6〗Smith问题 计算机将人们从繁重的计算中间,在计算机发明之前,人们必须靠手算,而且容易错。但现在,借助计算机,大量的计算也是瞬间而就。 但今天Smith教授遇到一个问题,他需要知道下列形式方程的整数解: x2?Ny2?1 其中N是一个正整数。但是对于很多N,教授的破计算机似乎找不到解。 “这就奇怪了”Smith教授说“一定是我的程序哪里出错了”。你,教授的助手,需要解决这个问题。 有多个测试序列。每个测试序列一行一个整数N (1 < =N < =10^8)。 对于每个测试序列,输出方程的在10^1000内的最小整数解X和Y,如果没有这样的解,输出一行\。 52 244· · 第16章 数论问题 256 991 649 90 No solution! 379516400906811930638014896080 12055735790331359447442538767 形如x2?Ny2?1的方程是所谓的Pell方程的特例,而起最小整数解可以用连分数法得到。也就是将N化成如下的形式: N?a0?a1?x?a0?y1a1?1??11?2?111?16,而 11 ??an1如果有ak?2a0,且 1ak?1,则(x,y)就是最小整数解。 14?3?例如 15?3?411?112?1,所以(15,4)就是方程 x2?14y2?1的最小整数解。 当然N是完全平方数时方程没有整数解,因为整数平方差不可能为1。 为了求得N的近似值,使用以下的递推方程: a0??N?p0?a0p1?a1p0?1pn?anpn?1?pn?2 q0?1q1?a1qn?anqn?1?qn?2这里的?x?表示下取整。计算另外两个数: ·245· ACM程序设计培训教程 P0?0P1?a0Pn?an?1Qn?1?Pn?2Q0?1n?Pn2Qn?Qn?1?a?Pn?an??0?Qn??可以证明数列满足下列两个重要性质: pnqn?1?pn?1qn???1?22pn?Nqn???1?n?1n?1Qn?1 所以方程的最小正整数解为 ??p,q??x,y???rr??p2r?1,q2r?1?r奇数r偶数 #include #define Base 1000000000 #define Cap 200 typedef __int64 hugeint; struct bignum { int Len; int Data[Cap]; bignum() : Len(0) {} bignum(const bignum& V) : Len(V.Len){ memcpy(Data, V.Data, Len * sizeof *Data);} bignum(int V) : Len(0) { for (; V > 0; V /= Base) Data[Len++] = V % Base; } bignum& operator=(const bignum& V) { Len = V.Len; memcpy(Data, V.Data, Len * sizeof *Data); return *this; } int& operator[](int Index) { return Data[Index]; } int operator[](int Index) const { return Data[Index]; } }; 246· ·