数论基本模型 下载本文

第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 #include #include using namespace std;

#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· ·