Loading

数论初步

1.欧几里德算法

int gcd(int a,int b)
{
    return b==0?a:gcd(b,a%b);
}

上面的算法即为欧几里德算法(Euclid algorithm),目的为求a与b的最大公约数。

gcd函数的递归成数不超过\(4.785\lg N+1.6723\),其中\(N=max\{a,b\}\)

利用gcd还可以求出两个整数a,b的最小公倍数lcm(a,b),可以用唯一分解定理证明,不难得到gcd(a,b)*lcm(a,b)=a*b,如果把lcm写成a*b/gcd(a,b)​,a*b可能会溢出,正确写法是a/gcd(a,b)*b

int lcm(a,b)
{
    return a/gcd(a,b)*b;
}

2.Eratosthenes 筛法

int m=sqrt(n+0.5);
memset(vis,0,sizeof(vis));
for(int i=2;i<=m;i++)
    if(!vis[i])
    	for(int j=i*i;j<=n;j+=i)
        	vis[j]=1;

对于不超过n的每个非负整数p,删除2p,3p,4p,…,当处理完所有数之后,还没有被删除的就是素数。上述代码中vis[i]表示i已被删除

内层循环不用从i*2开始——它已经在i=2时被筛掉了

3.扩展欧几里德算法

void gcd(int a,int b,int& d,int& x,int& y)
{
    if(!b)
    {
        d=a;
        x=1;
        y=0;
    }
    else
    {
        gcd(b,a%b,d,y,x);
        y-=x*(a/b);
    }
}

找出一对整数(x,y),使得\(ax+by=gcd(a,b)\),这里的x,y不一定是整数,也可能是负数或0。

如果要找多对则整数呢?

gcd(a,b)=g,任取另外一组解(x2,y2),则ax1+by1=ax2+by2,变形得a(x1-x2)=b(y2-y1),左右两边同时除以g,得a'(x1-x2)=b'(y2-y1),其中a’=a/g,b'=b/g。此时a’b'互素,因此x1-x2一定是b'得整数倍,设x1-x2kb',经计算得y2-y1=ka',所以得到如下结论

设a,b,c为任意整数。若方程ax+by=c得一组整数解为(x0,y0),则它的任意整数解都可以写成(x0+kb',y0-ka'),其中a'=a/gcd(a,b)b'=b/gcd(a,b),k取任意整数。

4.同余与模算术

\((a+b)mod\ n=((a\ mod\ n)+(b\ mod\ n))mod\ n\)

\((a-b)mod\ n=((a\ mod\ n)-(b\ mod\ n)+n)mod\ n\)

\(ab\ mod\ n=(a\ mod\ n)(b\ mod\ n)mod\ n\)

\(a\equiv b(mod\ n )\)的含义是“a和b除以n的余数相同”,其充要条件是“a-b是n的整数倍”。

大整数取模:输入正整数n和m,输出n mod m的值。\(n\leq10^{100},m\leq10^9\)

scanf("%s%d",n,&m);
int len=strlen(n);
int ans=0;
for(int i=0;i<len;i++)
    ans=(int)(((long long)ans*10+n[i]-'0')%m);
printf("%d\n",ans);

幂取模:输入正整数a,n和m,输出\(a^n\ mod\ m\)的值。\(a,n,m\leq 10^9\)

int pow_mod(int a,int n,int m)
{
    if(n==0)
        return 1;
    int x=pow_mod(a,n/2,m);
    long long ans=(long long)x*x%m;
    if(n%2==1)
        ans=ans*a%m;
    return (int)ans;
}
posted @ 2019-08-06 10:51  xaopng  阅读(212)  评论(0)    收藏  举报