技巧与错误(2)

来源:互联网 发布:淘宝怎样才能卖耐克 编辑:程序博客网 时间:2024/06/07 00:03

7.技巧 数论

    (1)基础知识,求两个数的最大公因数,一般使用经典的欧几里得算法,即用gcd(a,b)表示a,b的最大公因数,显然,当b==0时,返回a,否则返回gcd(b,a%b),也就是说gcd(a,b)==gcd(b,a%b),证明如下,为了证明两个数相等,由于两个数都是非负整数,所以我们只需要证明两个数能够互相整除就可以了:

    对于gcd(a,b)=c,因为c|a,且c|b,所以对于gcd(b,a%b),因为c|b,a%b=a/b*b,所以c|a%b,由于c|b,且c|a%b,所以gcd(a,b)一定整除gcd(b,a%b);

    同理,对于gcd(b,a%b)=d,因为d|b且d|a%b,a=a/b*b+a%b,所以d|a,所以gcd(b,a%b)一定整除gcd(a,b);

    证毕,代码如下:

int gcd(int a,int b){if(!b)return a;return gcd(b,a%b);}

    (2)如果遇到了一些讨厌的需要高精度gcd的题,那么我们可以使用针对大整数实现的二进制算法,思路如下:

    对于函数gcd(a,b)表示a,b,两个数的最大公因数;

    若a==b,则返回a(显然)。

    若a%2==0&&b%2==0,则返回2*gcd(a/2,b/2)(显然);

    若a%2==0&&b%2!=0,则返回gcd(a/2,b)(显然);

    若a%2!=0&&b%2!=0,则返回gcd(a-b,b)(容易证明,设t为gcd(a,b),则a=xt,b=yt,那么a-b=(x-y)*t,b=yt,因为x与y互质,所以不存在一个数c|y&&c|(x-y),所以gcd(a-b,b)=t);

    (3)若是求n个数的最大公因数?把第一个和第二个数合并为它们的gcd之后重复这个过程直到只剩下一个数就行。

    (4)gcd(n-p,n)<=p,证明如下:

    设gcd(n-p,n)=x,则n-p=ax,n=bx,两式相减,则p=(b-a)x,因为b>=a,所以p>=x,得证。

8.技巧 数论

    基础知识,对于两个数a,b我们将其分解质因数,则:

    a=p1^a1 * p2^a2 * ……pn^an;

    b=p1^b1 * p2^b2 * ……pm^bm;

    实际上我们所取的最大公因数就是p1^min(a1,b1) * p2^min(a2,b2)……相对的,最小公倍数就是把min改为max,显然,a*b/gcd(a,b)=lcm(a,b);

9.技巧 数论

    基础,拓展欧几里得算法,主要应用于求解形如ax+by=c的不定方程和形如(ax)%b=c的同余方程,二者实质是相同的,因为(ax)%b=c可以表示为ax=by+c,即ax+by=c;

    (1)算法思路如下:

    对于不定方程ax+by=c,设gcd(a,b)=d,首先我们判断此方程有无解的依据就是,d能否整除c,由于x,y均为整数,所以方程左边一定是d的倍数,若右边c不是d的倍数,那么显然无解,根据这个,对于上述方程,我们就可以将其转化为ax+by=d,最后对于求出来的答案乘一个c/d就行了。

    了解了上面那一点之后,我们设函数ex_gcd(a,b)表示求a,b的最大公因数并求出ax+by=d (d=gcd(a,b)) 的一组解x,y,算法思路如下:

    对于ex_gcd(a,b),当b==0时,显然d=a,有一组解为x=1,y=0;

    若b!=0,先求ex_gcd(b,a%b),则我们得到了bx1+(a%b)y1=d的一组解,因为a%b==a-a/b*b,所以,bx1+ay1-a/b*b*y1=d,整理得到ay1+b(x1-a/b*y1)=d,所以ex_gcd(a,b)的一组解就是x=y1,y=x1-a/b*y1,代码如下:

void ex_gcd(int a,int b,int &d,int &x,int &y){if(!b){d=a; x=1; y=0; return;}int t;ex_gcd(b,a%b,d,x,y);t=x; x=y; y=t-a/b*y;}
    (2)对于方程ax+by=c的通解与最小正整数解,解决思路如下:

    设ax1+by1=c;

        ax2+by2=c;

        两式相减,得到a(x1-x2)+b(y1-y2)=0,同除d=gcd(a,b),则(a/d)(x1-x2)+(b/d)(y1-y2)=0,所以x1=(b/d)(y2-y1)/(a/d)+x2,得到x1=x2+k*(b/d)  (k为整数).

        相对应的,y1=y2-k*(a/d),那么其最小正整数解x=(x1%(b/d)+(b/d))%(b/d)。

    (3)对于形如

    x%p1=b1;

    x%p2=b2;

    x%p3=b3;

    …………的方程的解法,我们首先先着眼于只有两个方程的情况,由于x=py+b1,x+py=b1,所以

    x1+p1y1=b1;

    x2+p2y2=b2;

    显然,当b1-p1y1=b2-p2y2的时候,x1与x2相等,所以我们只需要求出p1y1-p2y2=b1-b2的一组解,就可以求出相对应的那一个x1=b1-p1y1,那么两个方程就可以合并成一个新的方程x%lcd(p1,p2)=x1,重复这个过程就OK。

10.技巧 数论

    (1)对于一个数a,若将其分解质因素,则a=p1^a1 * p2^a2 * ……pn^an,那么它的因数个数s=(a1+1)*(a2+1)……(an+1);

    (2)所有因数的和为sum=[(p1^(a1+1)-1)/(p1-1)]*[(p2^(a2+1)-1)/(p2-1)]*……[(pn^(an+1)-1)/(pn-1)]。

    (3)求n!中质因子p的个数,代码如下:

int f(int n,int p){if(!n)return 0;return f(n/p,p)+n/p;}
    应用于求组合数的时候,分别对分子分母进行约分就可以使用这种方法;问n!末尾有多少个0?明显其答案为min(f(n,2),f(n,5)),即f(n,5),若是在十二进制下呢?因为12=2*2*3,所以明显是min(f(n,2)/2,f(n,3));



2 0
原创粉丝点击