[toc]
闲的无聊翻了一下快爆了的E盘,发现里面有不少“好东西“”,一堆关于数论的课件,所以就整理一下常见的数论模板。虽然我不会数论,但至少整理一下可以知道以后学什么(顺便水篇博客)
欧几里德:
#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,v=b,h为最小公约数=hcf(a,b); { return(u*v/h); } int main() { int a,b,x,y; cin>>a>>b; x=hcf(a,b); y=lcd(a,b,x); cout<<x<<" "<<y<<endl; return 0; }
扩展欧几里德
#include <iostream> using namespace std; __int64 ext_euclid(__int64 a,__int64 b, __int64 &x, __int64 &y) { int t; __int64 d; if (b==0) {x=1;y=0;return a;} d=ext_euclid(b,a %b,x,y); t=x; x=y; y=t-a/b*y; return d; } void modular_equation(__int64 a,__int64 b,__int64 c)//ax = b(mod n) { __int64 d; __int64 x,y; d = ext_euclid(a,b,x,y); if ( c % d != 0 ) printf("No answer "); else { x = (x * c/d) % b ;// 第一次求出的x ; __int64 t = b/d; x = (x%t + t)%t; printf("%I64d ",x);//最小的正数的值 for (int i=0;i<d;i++) printf("The %dth answer is : %ld ",i+1,(x+i*(b/d))%b); //所有的正数值 } } /*函数返回值为gcd(a,b),并顺带解出ax+by=gcd(a,b)的一个解x,y, 对于不定方程ax+by=c的通解为: x=x*c/d+b/d*t y=y*c/d+a/d*t 当c%gcd(a,b)!=0时,不定方程无解.*/
中国剩余定理:
#include <iostream> using namespace std; int ext_euclid(int a,int b,int &x,int &y) //求gcd(a,b)=ax+by { int t,d; if (b==0) {x=1;y=0;return a;} d=ext_euclid(b,a %b,x,y); t=x; x=y; y=t-a/b*y; return d; } int China(int W[],int B[],int k) //W为按多少排列,B为剩余个数 W>B K为组数 { int i; int d,x,y,a=0,m,n=1; for (i = 0;i<k;i++) n *= W[i]; for (i=0;i<k;i++) { m=n/W[i]; d=ext_euclid(W[i],m,x,y); a=(a+y*m*B[i])%n; } if (a>0) return a; else return(a+n); } int main() { int B[100],W[100]; 求 int k ; a = 2( mod 5 ) cin >> k ; a = 3( mod 13) for(int i = 0 ; i < k ;i++) 的解 { 2 cin >> W[i]; 5 2 cin >> B[i]; 13 3 } 输出 42 cout<<China(W,B,k)<<endl; return 0; }
欧拉函数:
求小于n的所有欧拉数
#include <iostream> using namespace std; int phi[1000]; //数组中储存每个数的欧拉数 void genPhi(int n)//求出比n小的每一个数的欧拉数(n-1的) { int i, j, pNum = 0 ; memset(phi, 0, sizeof(phi)) ; phi[1] = 1 ; for(i = 2; i < n; i++) { if(!phi[i]) { for(j = i; j < n; j += i) { if(!phi[j]) phi[j] = j; phi[j] = phi[j] / i * (i - 1); } } } } 求n的欧拉数 int eular(int n) { int ret=1,i; for (i=2;i*i<=n;i++) if (n%i==0) { n/=i,ret*=i-1; while (n%i==0) n/=i,ret*=i; } if (n>1) ret*=n-1; return ret; //n的欧拉数 }
行列式计算:
#include <iostream> using namespace std; int js(int s[100][100],int n) { int z,j,k,r,total=0; int b[100][100]; /*b[N][N]用于存放,在矩阵s[N][N]中元素s[0]的余子式*/ if(n>2) { for(z=0;z<n;z++) { for(j=0;j<n-1;j++) for(k=0;k<n-1;k++) if(k>=z) b[j][k]=s[j+1][k+1]; else b[j][k]=s[j+1][k]; if(z%2==0) r=s[0][z]*js(b,n-1); /*递归调用*/ else r=(-1)*s[0][z]*js(b,n-1); total=total+r; } } else if(n==2) total=s[0][0]*s[1][1]-s[0][1]*s[1][0]; return total; }
排列:
long A(long n,long m) //n>m { long a=1; while(m!=0) {a*=n;n--;m--;} return a; }
组合:
long C(long n,long m) //n>m { long i,c=1; i=m; while(i!=0) {c*=n;n--;i--;} while(m!=0) {c/=m;m--;} return c; }
大数乘大数:
#include <iostream> #include <string> using namespace std; char a[1000],b[1000],s[10000]; void mult(char a[],char b[],char s[]) //a被乘数,b乘数,s为积 { int i,j,k=0,alen,blen,sum=0,res[65][65]={0},flag=0; char result[65]; alen=strlen(a);blen=strlen(b); for (i=0;i<alen;i++) for (j=0;j<blen;j++) res[i][j]=(a[i]-'0')*(b[j]-'0'); for (i=alen-1;i>=0;i--) { for (j=blen-1;j>=0;j--) sum=sum+res[i+blen-j-1][j]; result[k]=sum%10; k=k+1; sum=sum/10; } for (i=blen-2;i>=0;i--) { for (j=0;j<=i;j++) sum=sum+res[i-j][j]; result[k]=sum%10; k=k+1; sum=sum/10; } if (sum!=0) {result[k]=sum;k=k+1;} for (i=0;i<k;i++) result[i]+='0'; for (i=k-1;i>=0;i--) s[i]=result[k-1-i]; s[k]='