数论基础代码合集

举报
兔老大 发表于 2021/04/22 01:31:08 2021/04/22
【摘要】 欧几里德 #include<iostream>using namespace std;int hcf(int a,int b)      {    int r=0;    while(b!=0)    {        r=a%b;        a=b;        b=r;    }    return(a);}lcd(int u,int v,int h) //u=a...

欧几里德


  
  1. #include<iostream>
  2. using namespace std;
  3. int hcf(int a,int b)      
  4. {
  5.     int r=0;
  6.     while(b!=0)
  7.     {
  8.         r=a%b;
  9.         a=b;
  10.         b=r;
  11.     }
  12.     return(a);
  13. }
  14. lcd(int u,int v,int h) //u=a,v=b,h为最小公约数=hcf(a,b);
  15. {
  16.     return(u*v/h);
  17. }
  18. int main()
  19. {
  20.        int a,b,x,y;
  21.        cin>>a>>b;
  22.        x=hcf(a,b);
  23.        y=lcd(a,b,x);
  24.        cout<<x<<" "<<y<<endl;
  25.        return 0;
  26. }

扩展欧几里德


  
  1. #include <iostream>
  2. using namespace std;
  3. __int64 ext_euclid(__int64 a,__int64 b, __int64 &x, __int64 &y)
  4. {
  5.     int t;
  6.        __int64 d;
  7.     if (b==0) {x=1;y=0;return a;}
  8.     d=ext_euclid(b,a %b,x,y);
  9.     t=x;
  10.     x=y;
  11.     y=t-a/b*y;
  12.     return d;
  13. }
  14. void modular_equation(__int64 a,__int64 b,__int64 c)//ax = b(mod n)
  15. {
  16.     __int64 d;
  17.     __int64 x,y;
  18.     d = ext_euclid(a,b,x,y);
  19.     if ( c % d != 0 )
  20.               printf("No answer\n");
  21.     else
  22.     {
  23.               x = (x * c/d) % b ;// 第一次求出的x ;
  24.               __int64 t = b/d;
  25.               x = (x%t + t)%t;
  26.               printf("%I64d\n",x);//最小的正数的值
  27.               for (int i=0;i<d;i++)
  28.                      printf("The %dth answer is : %ld\n",i+1,(x+i*(b/d))%b); //所有的正数值
  29.     }
  30. }
  31. /*
  32. 函数返回值为gcd(a,b),并顺带解出ax+by=gcd(a,b)的一个解x,y,
  33.   对于不定方程ax+by=c的通解为:
  34.   x=x*c/d+b/d*t
  35.   y=y*c/d+a/d*t
  36. 当c%gcd(a,b)!=0时,不定方程无解.*/

 

中国剩余定理


  
  1. #include <iostream>
  2. using namespace  std;
  3.  int ext_euclid(int a,int b,int &x,int &y)  //求gcd(a,b)=ax+by
  4. {
  5.     int t,d;
  6.     if (b==0) {x=1;y=0;return a;}
  7.     d=ext_euclid(b,a %b,x,y);
  8.     t=x;
  9.     x=y;
  10.     y=t-a/b*y;
  11.     return d;
  12. }
  13. int China(int W[],int B[],int k)   //W为按多少排列,B为剩余个数   W>B  K为组数
  14. {
  15.     int i;
  16.     int d,x,y,a=0,m,n=1;
  17.     for (i = 0;i<k;i++)
  18.         n *= W[i];
  19.     for (i=0;i<k;i++)
  20.        {
  21.               m=n/W[i];
  22.         d=ext_euclid(W[i],m,x,y);
  23.         a=(a+y*m*B[i])%n;
  24.        }
  25.     if (a>0
  26.               return a;
  27.     else
  28.               return(a+n);
  29. }
  30. int main()
  31. {
  32.        int B[100],W[100];                                求
  33.        int k ;                                           a = 2( mod 5 )
  34.        cin >> k ;                                        a = 3( mod 13)
  35.        for(int i = 0 ; i < k ;i++)                            的解
  36.        {                                               2
  37.               cin >> W[i];                                  5 2
  38.               cin >> B[i];                                   13 3 
  39.        }                                               输出 42
  40.        cout<<China(W,B,k)<<endl;
  41.        return 0;
  42. }

 

欧拉函数

求小于n的所有欧拉数


  
  1. #include <iostream>
  2. using namespace std;
  3. int phi[1000];     //数组中储存每个数的欧拉数
  4. void genPhi(int n)//求出比n小的每一个数的欧拉数(n-1的)
  5. {
  6.        int i, j, pNum = 0 ;
  7.        memset(phi, 0, sizeof(phi)) ;
  8.        phi[1] = 1 ;
  9.        for(i = 2; i < n; i++)
  10.        {
  11.               if(!phi[i])
  12.               {
  13.                      for(j = i; j < n; j += i)
  14.                      {
  15.                             if(!phi[j])
  16.                                    phi[j] = j;
  17.                             phi[j] = phi[j] / i * (i - 1);
  18.                      }
  19.               }
  20.        }
  21. }

n的欧拉数


  
  1. int eular(int n)
  2. {
  3.        int ret=1,i;
  4.        for (i=2;i*i<=n;i++)
  5.               if (n%i==0)
  6.               {
  7.                      n/=i,ret*=i-1;
  8.                      while (n%i==0)
  9.                             n/=i,ret*=i;
  10.               }
  11.               if (n>1)
  12.                      ret*=n-1;
  13.               return ret;    //n的欧拉数
  14. }

行列式计算


  
  1. #include <iostream>
  2. using namespace std;
  3. int js(int s[100][100],int n)
  4. {
  5.     int z,j,k,r,total=0;
  6.     int b[100][100];  /*b[N][N]用于存放,在矩阵s[N][N]中元素s[0]的余子式*/
  7.     if(n>2)
  8.        {
  9.         for(z=0;z<n;z++)
  10.               {
  11.             for(j=0;j<n-1;j++)
  12.               for(k=0;k<n-1;k++)
  13.                      if(k>=z)
  14.                              b[j][k]=s[j+1][k+1]; 
  15.                      else
  16.                             b[j][k]=s[j+1][k];
  17.                      if(z%2==0)
  18.                             r=s[0][z]*js(b,n-1); /*递归调用*/
  19.                      else
  20.                             r=(-1)*s[0][z]*js(b,n-1);
  21.                      total=total+r;
  22.               }
  23.        }
  24.     else if(n==2)
  25.               total=s[0][0]*s[1][1]-s[0][1]*s[1][0];
  26.     return total;
  27. }

排列


  
  1. long A(long n,long m)   //n>m
  2. {
  3.     long a=1;
  4.     while(m!=0)  {a*=n;n--;m--;}
  5.     return a;
  6. }

组合


  
  1. long C(long n,long m)     //n>m
  2. {
  3.     long i,c=1;
  4.     i=m;
  5.     while(i!=0)   {c*=n;n--;i--;}
  6. while(m!=0)  {c/=m;m--;}
  7. return c;
  8. }

大数乘大数


  
  1. #include <iostream>
  2. #include <string>
  3. using namespace std;
  4. char a[1000],b[1000],s[10000];
  5. void mult(char a[],char b[],char s[])     //a被乘数,b乘数,s为积
  6. {
  7.     int i,j,k=0,alen,blen,sum=0,res[65][65]={0},flag=0;
  8.     char result[65];
  9.     alen=strlen(a);blen=strlen(b);
  10.     for (i=0;i<alen;i++)
  11.     for (j=0;j<blen;j++) res[i][j]=(a[i]-'0')*(b[j]-'0');
  12.     for (i=alen-1;i>=0;i--)
  13.         {
  14.             for (j=blen-1;j>=0;j--) sum=sum+res[i+blen-j-1][j];
  15.             result[k]=sum%10;
  16.             k=k+1;
  17.             sum=sum/10;
  18.         }
  19.     for (i=blen-2;i>=0;i--)
  20.         {
  21.             for (j=0;j<=i;j++) sum=sum+res[i-j][j];
  22.             result[k]=sum%10;
  23.             k=k+1;
  24.             sum=sum/10;
  25.         }
  26.     if (sum!=0) {result[k]=sum;k=k+1;}
  27.     for (i=0;i<k;i++) result[i]+='0';
  28.     for (i=k-1;i>=0;i--) s[i]=result[k-1-i];
  29.     s[k]='\0';
  30.     while(1)
  31.         {
  32.         if (strlen(s)!=strlen(a)&&s[0]=='0')
  33.             strcpy(s,s+1);
  34.         else
  35.             break;
  36.         }
  37. }
  38. int main()
  39. {
  40.        cin>>a>>b;
  41.        mult(a,b,s);
  42.        cout<<s<<endl;
  43.        return 0;}

大数乘小数


  
  1. #include <iostream>
  2. using namespace std;
  3. char a[100],t[1000];
  4. void mult(char c[],int m,char t[])  // c为大数,m<=10,t为积
  5. {
  6.     int i,l,k,flag,add=0;
  7.     char s[100];
  8.     l=strlen(c);
  9.     for (i=0;i<l;i++)
  10.         s[l-i-1]=c[i]-'0';
  11.     for (i=0;i<l;i++)
  12.        {
  13.               k=s[i]*m+add;
  14.               if (k>=10)
  15.               {
  16.                      s[i]=k%10;add=k/10;flag=1;
  17.               }
  18.               else
  19.               {
  20.                      s[i]=k;flag=0;add=0;
  21.               }
  22.        }
  23.     if (flag)
  24.        {
  25.               l=i+1;s[i]=add;
  26.        }
  27.        else
  28.               l=i;
  29.     for (i=0;i<l;i++)
  30.         t[l-1-i]=s[i]+'0';
  31.     t[l]='\0';
  32. }
  33. int main()
  34. {
  35.        int i;
  36.        cin>>a>>i;
  37.        mult(a,i,t);
  38.        cout<<t<<endl;
  39.        return 0;
  40. }

大数加法


  
  1. #include <iostream>
  2. #include <string>
  3. using namespace std;
  4. char a[1000],b[1000],s[10000];
  5. void add(char a[],char b[],char s[])//a被加数,b加数,s和
  6. {
  7.     int i,j,k,up,x,y,z,l;
  8.     char *c;
  9.     if (strlen(a)>strlen(b)) l=strlen(a)+2; else l=strlen(b)+2;
  10.     c=(char *) malloc(l*sizeof(char));
  11.     i=strlen(a)-1;
  12.     j=strlen(b)-1;
  13.     k=0;up=0;
  14.     while(i>=0||j>=0)
  15.        {
  16.               if(i<0) x='0'; else x=a[i];
  17.               if(j<0) y='0'; else y=b[j];
  18.               z=x-'0'+y-'0';
  19.               if(up) z+=1;
  20.               if(z>9) {up=1;z%=10;} else up=0;
  21.               c[k++]=z+'0';
  22.               i--;j--;
  23.        }
  24.     if(up) c[k++]='1';
  25.     i=0;
  26.     c[k]='\0';
  27.     for(k-=1;k>=0;k--)
  28.         s[i++]=c[k];
  29.     s[i]='\0';
  30. }
  31. int main()
  32. {
  33.        cin>>a>>b;
  34.        add(a,b,s);
  35.        cout<<s<<endl;
  36.        return 0;
  37. }

 

大数减法


  
  1. #include <iostream>
  2. using namespace std;
  3. char a[1000],b[1000],s[10000];
  4. void sub(char a[],char b[],char s[])
  5. {
  6.     int i,l2,l1,k;
  7.     l2=strlen(b);l1=strlen(a);
  8.     s[l1]='\0';l1--;
  9.     for (i=l2-1;i>=0;i--,l1--)
  10.         {
  11.         if (a[l1]-b[i]>=0)
  12.             s[l1]=a[l1]-b[i]+'0';
  13.         else
  14.             {
  15.             s[l1]=10+a[l1]-b[i]+'0';
  16.             a[l1-1]=b[l1-1]-1;
  17.             }
  18.         }
  19.     k=l1;
  20.     while(a[k]<0) {a[k]+=10;a[k-1]-=1;k--;}
  21.     while(l1>=0) {s[l1]=a[l1];l1--;}
  22. loop:
  23.     if (s[0]=='0')
  24.         {
  25.         l1=strlen(a);
  26.         for (i=0;i<l1-1;i++) s[i]=s[i+1];
  27.         s[l1-1]='\0';
  28.         goto loop;
  29.         }
  30.     if (strlen(s)==0) {s[0]='0';s[1]='\0';}
  31. }
  32. int main()
  33. {
  34.        cin>>a>>b;
  35.        sub(a,b,s);
  36.        cout<<s<<endl;
  37.        return 0;
  38. }

 

大数阶乘


  
  1. #include <iostream>
  2. #include <cmath>
  3. using namespace std;
  4. long a[10000];
  5. int factorial(int n)         //n为所求阶乘的n!的n
  6. {
  7.        int i,j,c,m=0,w;
  8.        a[0]=1;
  9.        for(i=1;i<=n;i++)
  10.    {
  11.               c=0;
  12.               for(j=0;j<=m;j++)
  13.        {
  14.                      a[j]=a[j]*i+c;
  15.                      c=a[j]/10000;
  16.                      a[j]=a[j]%10000;
  17.            }
  18.               if(c>0) {m++;a[m]=c;}
  19.        }
  20.        w=m*4+log10(a[m])+1;
  21.        printf("%ld",a[m]); //        输出
  22.        for(i=m-1;i>=0;i--) //
  23.               printf("%4.4ld",a[i]);//
  24.        printf("\n");
  25.        return w;            //返回值为阶乘的位数
  26. }

 

储存方法很巧,每一个a[i]中存四位,不足四位在前加0补齐

 

 

大数求余


  
  1. int mod(int B)     //A为大数,B为小数
  2. {
  3.        int i = 0,r = 0;
  4.        while( A[i] != '\0' )
  5.        {
  6.               r=(r*10+A[i++]-'0')%B;
  7.        }
  8.     return r ;    //r为余数
  9. }

高精度任意进制转换


  
  1. #include <iostream>
  2. #include <string>
  3. using namespace std;
  4. char s[1000],s2[1000];   // s[]:原进制数字,用字符串表示,s2[]:转换结果,用字符串表示
  5. long d1,d2;   // d1:原进制数,d2:需要转换到的进制数
  6. void conversion(char s[],char s2[],long d1,long d2)
  7. {
  8.     long i,j,t,num;
  9.     char c;
  10.     num=0;
  11.     for (i=0;s[i]!='\0';i++)
  12.        {
  13.         if (s[i]<='9'&&s[i]>='0') t=s[i]-'0'; else t=s[i]-'A'+10;
  14.         num=num*d1+t;
  15.        }
  16.     i=0;
  17.     while(1)
  18.        {
  19.         t=num%d2;
  20.         if (t<=9) s2[i]=t+'0'; else s2[i]=t+'A'-10;
  21.         num/=d2;
  22.         if (num==0) break;
  23.         i++;
  24.        }
  25.     for (j=0;j<=i/2;j++)
  26.        {c=s2[j];s2[j]=s2[i-j];s2[i-j]=c;}
  27.     s2[i+1]='\0';
  28. }
  29. int main()
  30. {
  31.        while (1)
  32.        {
  33.               cin>>s>>d1>>d2;
  34.               conversion(s,s2,d1,d2);
  35.               cout<<s2<<endl;
  36.        }
  37.        return 0;
  38. }

判断一个数是否素数

#include <iostream>//基本方法,n为所求数,返回1位素数,0为合数

#include <cmath>

using namespace std;

int comp(int n){

int i,flag=1;

    for (i=2;i<=sqrt(n);i++)

    if (n%i==0) {flag=0;break;}

    if (flag==1) return 1; else return 0;}

素数表


  
  1. int prime(int a[],int n)            //小于n的素数
  2. {   int i,j,k,x,num,*b;
  3.     n++;
  4.     n/=2;
  5.     b=(int *)malloc(sizeof(int)*(n+1)*2);
  6.     a[0]=2;a[1]=3;num=2;
  7.     for(i=1;i<=2*n;i++)
  8.         b[i]=0;
  9.     for(i=3;i<=n;i+=3)
  10.         for(j=0;j<2;j++)
  11.             {
  12.             x=2*(i+j)-1;
  13.             while(b[x]==0)
  14.                 {
  15.                 a[num++]=x;
  16.                 for(k=x;k<=2*n;k+=x)
  17.                     b[k]=1;
  18.                 }
  19.             }
  20.     return num; }                //小于n的素数的个数}
  21. bool flag[1000000];
  22. void prime(int M)               //01表
  23. {     int i , j;
  24.        int sq = sqrt(double(M));     
  25.        for(i = 0 ;i < M ;i ++)
  26.               flag[i] = true;    
  27.        flag[1] = false;   flag[0] = false;
  28.        for(i = 2 ;i <= sq ;i++)
  29.               if(flag[i])
  30.               {
  31.                      for(j = i*i ;j < M ;j += i)
  32.                             flag[j] = false;
  33.               }
  34. }

     Miller_Rabin随机素数测试算法    

        说明:这种算法可以快速地测试一个数是否  

        满足素数的必要条件,但不是充分条件。不  

        过也可以用它来测试素数,出错概率很小,  

        对于任意奇数n>2和正整数s,该算法出错概率  

        至多为2^(-s),因此,增大s可以减小出错概  

        率,一般取s=50就足够了。


  
  1. #include<iostream>
  2. #include <cmath>
  3. using namespace std;
  4. int Witness(int a, int n)  
  5. {  
  6.        int i, d = 1, x;  
  7.        for (i = ceil( log( (float) n - 1 ) / log(2.0) ) - 1; i >= 0; i--)    
  8.        {  
  9.               x = d;  
  10.               d = (d * d) % n;  
  11.               if ( (d == 1) && (x != 1) && (x != n-1) )
  12.                      return 1;  
  13.               if ( ( (n - 1) & ( 1<<i ) ) >0 )
  14.                      d = (d * a) % n;  
  15.        }  
  16.        return (d == 1 ? 0 : 1);          
  17. }  
  18. int Miller_Rabin(int n, int s)  
  19. {  
  20.        int j, a;  
  21.        for (j = 0; j < s; j++)  
  22.        {    
  23.               a = rand() * (n - 2) / RAND_MAX + 1;  
  24.               if (Witness(a, n))
  25.                      return 0;  
  26.        }  
  27.        return 1;        
  28. }  
  29. int main()
  30. {
  31.        int x;
  32.        cin>>x;
  33.        cout<<Miller_Rabin(x , 50)<<endl;
  34.        return 0;
  35. }

 

整数拆分不可重复


  
  1. #include <iostream>
  2. #include <memory>
  3. using namespace std;
  4. const int MAX = 500;
  5. long long data[MAX][MAX];
  6. int main()
  7. {
  8.        int i,j;
  9.        memset(data, 0, sizeof(int)*MAX);
  10.        for(i = 0; i < MAX; i++)
  11.               data[0][i] = 0;
  12.        for(i = 0; i < MAX; i++)
  13.        {
  14.               for(j = 0; j < MAX; j++)
  15.               {
  16.                      int sum = j*(j+1)/2;
  17.                      if(i > sum) data[i][j] = 0;
  18.                      else if(i == sum) data[i][j] = 1;
  19.                      else
  20.                      {
  21.                             if(i == j) data[i][j] = 1 + data[i][j-1];
  22.                             else if(i < j) data[i][j] = data[i][i];
  23.                             else data[i][j] = data[i-j][j-1] + data[i][j-1];
  24.                      }
  25.               }
  26.        }
  27.        int n;
  28.        while(cin >> n)
  29.               cout << data[n][n] << endl;
  30.        return 0;
  31. }
  32. 整数拆分积最大
  33. int data[100];
  34. void main(int n;)
  35. {      int k = 2;
  36.        for(; n >= k; n-=k,k++)
  37.               data[k] = k;
  38.        for(int i = k-1; i >= 2 && n; i--, n--)
  39.               data[i]++;
  40.        data[k-1] += n;
  41.        for(int j = 2; j < k; j++)
  42.               cout << data[j] << " ";
  43.        cout << endl; }

整数的无序拆分(可重复)


  
  1. #include <iostream>       //求出可分解个数
  2. #include <memory>
  3. using namespace std;
  4. const int MAX = 600;
  5. long long data[MAX][MAX];
  6. int main()
  7. {
  8.        int i,j;
  9.        memset(data, 0, sizeof(int)*MAX);
  10.        for(j = 0; j < MAX; j++)
  11.               data[0][j] = 0;
  12.        for(i = 1; i < MAX; i++)
  13.        {
  14.               for(j = 1; j < MAX; j++)
  15.               {
  16.                      if(i == j)
  17.                             data[i][j] = data[i][j-1]+1;
  18.                      else if(i < j)
  19.                             data[i][j] = data[i][i];
  20.                      else
  21.                             data[i][j] = data[i][j-1]+data[i-j][j];
  22.               }
  23.        }     
  24.        int n;
  25.        while(cin >> n)
  26.               cout << data[n][n] << endl;
  27.        return 0;
  28. }

整数的无序拆分(可重复)


  
  1. #include <iostream>   //列出分解情况
  2. #include <memory>
  3. using namespace std;
  4. const int MAX = 300;
  5. int data[MAX];
  6. int main()
  7. {
  8.        int i,n;
  9.        cin >> n;
  10.        for(i = 0; i < n; i++)
  11.        {
  12.               data[i] = 1;
  13.               printf("1");
  14.        }
  15.        printf("\n");
  16.        int size = n;
  17.        while(size > 1)
  18.        {
  19.               int t, p, r;
  20.               t = data[size-1] + data[size-2];
  21.               p = t / (data[size-2]+1);
  22.               r = t % (data[size-2]+1);
  23.              
  24.               t = data[size-2]+1;
  25.               i = size - 2;
  26.               size = size - 2 + p;
  27.               for(; i < size; i++)
  28.                      data[i] = t;
  29.               data[size-1] += r;
  30.              
  31.               for(i = 0; i < size; i++)
  32.                      printf("%d", data[i]);
  33.               printf("\n");
  34.        }
  35.        return 0;
  36. }

约瑟夫环


  
  1. void f()
  2. {
  3.        int n , k , m , i , j , start;
  4.        while(cin>>n>>k>>m )   //n代表有多少个人 , k表示叫到k的人出列 , m 表示第一次谁先开始叫
  5.        {
  6.               start = 0;
  7.               if( !n && !k && !m)
  8.                      return 0;
  9.               for(i = 1 ;i < n; i++)
  10.               {
  11.                      start = (start + k) % i;
  12.               }
  13.               start++;
  14.               start = (start + m) % n;
  15.               if(!start)
  16.                      cout<<n<<endl;
  17.               else
  18.                      cout<<start<<endl;
  19.        }
  20.        return ;
  21. }
  22. #include <stdio.h>
  23. main()
  24. {
  25.    int n, m, i, s=0;
  26.    printf ("N M = "); scanf("%d%d", &n, &m);
  27.    for (i=2; i<=n; i++) s=(s+m)%i;
  28.    printf ("The winner is %d\n", s+1);
  29. }

 

文章来源: fantianzuo.blog.csdn.net,作者:兔老大RabbitMQ,版权归原作者所有,如需转载,请联系作者。

原文链接:fantianzuo.blog.csdn.net/article/details/104085092

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。