数论

来源:互联网 发布:吉林省互联网 公安软件 编辑:程序博客网 时间:2024/06/03 11:09

数论:

1.    求n^n的最高位数字。1<=N<=1,000,000

(int)a=10^(n*lg(n)-floor(lg(n^n)))

 

2.    计算比n小的数中与n不互质的数的和%1000000007

n*(n-1)/2-n*phi(n)/2

 

3. 抽屉原理的运用

抽屉原理本身只是一句废话,不过他的运用却非常强大

现在假设有一个正整数序列a1,a2,a3,a4.....an,试证明我们一定能够找到一段连续的序列和,让这个和是n的倍数,该命题的证明就用到了抽屉原理

我们可以先构造一个序列si=a1+a2+...ai

然后分别对于si取模,如果其中有一个sk%n==0,那么a1+a2+...+ak就一定是n的倍数(该种情况得证)

下面是上一种情况的反面,即任何一个sk对于n的余数都不为0

对于这种情况,我们可以如下考虑,因为si%n!=0

那么si%n的范围必然在1——(n-1),所以原序列si就产生了n个范围在1——(n-1)的余数,于是抽屉原理就来了,n个数放进n-1个盒子里面,必然至少有两个余数会重复,那么这两个sk1,sk2之差必然是n的倍数,

而sk1-sk2是一段连续的序列,那么原命题就得到了证明了

 

 

4. 判断n!是否能够被m整除

计算方法是把m进行质因数分解,看下m的每一个质因数是否能够在n!中找到;

n!中间包含了多少个x(x是任意的一个数,不过一般情况下我们都只讨论x为质数),这种问题的答案是:
n/x+n/(x^2)+n/(x^3).....[一直加到x的乘方不超过n],这个定理的证明也非常的简单,这里就不再赘述了

根据以上观点,就可以分别计算m的每一个质因数是否被完全包含,如果有一个没有被包含,那么就不能被整除!

 

 

5. 判断组合数C(n,m)的奇偶性

当n&m==m为奇数,反之就是偶数

 

 

6.欧几里德扩展

ax+by=c

对于不定方程ax+by=c的通解为:

x=x*c/d+b/d*t  

y=y*c/d+a/d*t  

当c%gcd(a,b)!=0时,不定方程无解.

 

 

7.乘法逆元

ax=1 mod m .可以化成ax+my=1;

 

 

8.同余模

(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

在减法中,由于a mod n可能小于b mod n,需要在结果上加上n

其他乘除同理

 

9.根据费马小定理

a^x%p=a^(x%(p-1))%p

 

10.n=p(1)^num[1]* p(2)^num[2]*….. p(m)^num[m]n的因子数有(num[1]+1)*…(num[m]+1)

 

11. 点到线段最短距离

语法:

result=mindistance(Point p1,Pointp2,Point q);

参数:

p1、p2:线段的两个端点q:判断点返回值:点q到线段p1p2的距离

源程序

typedef struct

{ double x,y;

} Point;

double mindistance(Point p1,Pointp2,Point q)

{ int flag=1;    

    double  k;

    Point s;

    if (p1.x==p2.x){s.x=p1.x;s.y=q.y;flag=0;}

    if(p1.y==p2.y){s.x=q.x;s.y=p1.y;flag=0;}

    if(flag) {

        k=(p2.y-p1.y)/(p2.x-p1.x);

       s.x=(k*k*p1.x+k*(q.y-p1.y)+q.x)/(k*k+1);

        s.y=k*(s.x-p1.x)+p1.y;

    }

    if(MIN(p1.x,p2.x)<=s.x&&s.x<=MAX(p1.x,p2.x))      

        return  sqrt((q.x-s.x)*(q.x-s.x)+(q.y-s.y)*(q.y-s.y));

    else

        returnMIN(sqrt((q.x-p1.x)*(q.x-p1.x)+(q.y-p1.y)*(q.y-p1.y)),sqrt((q.x-p2.x)*(q.x-p2.x

     )+(q.y-p2.y)*(q.y-p2.y)));

 }

 

12.求两直线的交点

语法:result=mindistance(Pointp1,Point p2,Point q);

 通过指针返回结果返回值:1:两直线相交;2:两直线平行

 注意:如需要判断两线段交点,检验k 和对应 k1(注释中)的值是否在0~1之间,用在0~1之间的那个求交点

 源程序:

 typedef struct

{

       double x,y; 

} Point;

 int linecorss(Point p1,Pointp2,Point p3,Point p4,Point *p)

{

   double k;

    if((p4.x-p3.x)*(p1.y-p3.y)-(p4.y-p3.y)*(p1.x-p3.x)==0&&  

       (p2.x-p1.x)*(p1.y-p3.y)-(p2.y-p1.y)*(p1.x-p3.x)==0) return 2;

    if((p4.y-p3.y)*(p2.x-p1.x)-(p4.x-p3.x)*(p2.y-p1.y)==0) return 0;

k=((p4.x-p3.x)*(p1.y-p3.y)-(p4.y-p3.y)*(p1.x-p3.x))/((p4.y-p3.y)*(p2.x-p1.x)-(p4.x-p3.x)*(p2.y-p1.y)); 

//k1=((p2.x-p1.x)*(p1.y-p3.y)-(p2.y-p1.y)*(p1.x-p3.x))/((p4.y-p3.y)*(p2.x-p1.x)-(p4.x-p3.x)*(p2.y-p1.y)); 

 (*p).x=p1.x+k*(p2.x-p1.x); 

 (*p).y=p1.y+k*(p2.y-p1.y); 

 return 1;//有交点

}

13. 叉乘法求任意多边形面积  语法:result=polygonarea(Point *polygon,int N);

参数:*polygon: 多变形顶点数组  N: 多边形顶点数目 返回值: 多边形面积

注意:支持任意多边形,凹、凸皆可   

多边形顶点输入时按顺时针顺序排列

 源程序:  

typedefstruct {     double x,y; } Point;   double polygonarea(Point *polygon,int N){      int i,j;      double area = 0;      for (i=0;i<N;i++) {         j = (i + 1) % N;          area += polygon[i].x *polygon[j].y;         area -=polygon[i].y * polygon[j].x;        }      area /= 2;      return(area < 0 ? -area : area); }

14. 求三角形面积 

语法:result=area3(float x1,float y1,float x2,floaty2,float x3,float y3); 参数:  x1~3: 三角形3个顶点x坐标 y1~3: 三角形3个顶点y坐标 返回值: 三角形面积

 注意需要 math.h 

源程序:      float area3(float x1,float y1,float x2,float y2,float x3,float y3){      float a,b,c,p,s;      a=sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));     b=sqrt((x1-x3)*(x1-x3)+(y1-y3)*(y1-y3));    c=sqrt((x3-x2)*(x3-x2)+(y3-y2)*(y3-y2));     p=(a+b+c)/2;      s=sqrt(p*(p-a)*(p-b)*(p-c));     return s; } 

 

 

15.两点距离(2D、3D) 

语法:result=distance_2d(float x1,float x2,floaty1,float y2); 参数: x/y/z1~ 2:  各点的x、y、z坐标 返回值: 两点之间的距离 注意:      需要 math.h

 源程序:    floatdistance_2d(float x1,float x2,float y1,float y2)  {     return(sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2))); }  float distance_3d(float x1,float x2,floaty1,float y2,float z1,float z2)  {return(sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)+(z1-z2)*(z1-z2)));}

 

16.整数拆分不可重复的个数

longlong data[maxn][maxn];

int main(){

    int i,j;

    memset(data, 0, sizeof(int)*maxn);

    for(i = 0; i< maxn; i++)

        data[0][i] = 0;

    for(i = 0; i< maxn;i++)  {

        for(j = 0; j< maxn;j++)   {

            int sum =j*(j+1)/2;

            if(i >sum)

                data[i][j]= 0;

            else if(i ==sum)

                data[i][j]= 1;

            else    {

                if(i ==j)

                    data[i][j]=1 + data[i][j-1];

                else if(i <j) data[i][j]= data[i][i];

                else data[i][j]= data[i-j][j-1] + data[i][j-1];

            }

        }

    }

    int n;

    while(cin>> n)

        cout<< data[n][n]<< endl;

    return 0;

}

17.整数的无序拆分(可重复)//求出可分解个数

longlong data[MAX][MAX];

int main(){

    int i,j;

    memset(data, 0, sizeof(int)*MAX);

    for(j = 0; j< MAX; j++)

        data[0][j] = 0;

    for(i = 1; i< MAX;i++)  {

        for(j = 1; j< MAX;j++)   {

            if(i ==j)

                data[i][j]= data[i][j-1]+1;

            else if(i <j)

                data[i][j]= data[i][i];

            else      data[i][j]= data[i][j-1]+data[i-j][j];

        }

    }

    int n;

    while(cin>> n)

        cout<< data[n][n]<< endl;

    return 0;

}

 

18.整数的无序拆分//列出分解情况

int data[MAX];

int main(){

    int i,n;

    cin>> n;

    for(i = 0; i< n; i++)  {

        data[i] = 1;

        printf("1");

    }

    printf("\n");

    int size =n;

    while(size> 1)  {

        int t, p,r;

        t = data[size-1] + data[size-2];

        p = t / (data[size-2]+1);

        r = t % (data[size-2]+1);

        t = data[size-2]+1;

        i = size - 2;

        size = size - 2 + p;

        for(; i< size; i++)

            data[i] =t;

        data[size-1] += r;

        for(i = 0; i< size; i++)

            printf("%d", data[i]);

        printf("\n");

    }

    return 0;

}


19.

大整数取模 n mod m ,n<=10^100,m<=10^9

scanf("%s%d",n,&m);

intl=strlen(n);

int ans=0;

for(int i=0;i<l;i++)

ans=(int)(((long long)ans*10+n[i]-'0')%m);

cout<<ans<<endl;


20.幂取模

a^n mod m,   a,n,m<=10^9 O(logn)

intpow_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;

}

21.ax ≡b(mod n)  ax和b除于n有相同的余数,说明ax-b是

n的倍数,所以ax-b=ny,y为倍数,ax-ny=b;


原创粉丝点击