整除
Eratosthenes筛选法求素数
const int range=1000000; //求素数的范围
int *p=new int[range+1]; //存储该范围内所有数的数组
void eratosthenes(int *p) { //Eratosthenes筛选法
for(int i=2;i<=ceil(sqrt(range));i++)
for(int j=2*i;j<=range;j+=i) //将i的倍数都赋成0
p[j]=0;
}
int main() {
for(int i=0;i<=range;i++) //初始化数组
p[i]=i;
p[1]=0;
eratosthenes(p);
int count=0;
for(int i=2;i<=range;i++) { //遍历数组
if(p[i]!=0) { //输出不为0的数(即素数)
cout<<p[i]<<" ";
count++;
if(count%5==0) //5个一行
cout<<endl;
}
}
return 0;
}
辗转相除法求最大公因子
int gcd(int a,int b) { //辗转相除法
if(a<b) //a为大的那个数
swap(a, b);
int r=a%b; //余数
while(r!=0) { //当余数不为0时
a=b;
b=r;
r=a%b;
}
return b;
}
求素因子分解
void deposition(int n) { //求素因子分解
for(int i=2;i<=n;i++) { //遍历
int count=0; //次幂
while(n%i==0) { //如果能整除
count++; //次数+1
n/=i; //除掉因子
}
if(count!=0) { //输出分解式
cout<<i;
if(count!=1)
cout<<"^"<<count;
if(n!=1)
cout<<"×";
else break;
}
}
}
同余
求正整数的欧拉函数
//只要稍微改动一下求素因子分解的函数即可
int euler=1; //欧拉函数
euler*=(1-1/double(i)); //计算欧拉函数,i为素因子
拓展欧几里得算法求乘法逆元
int inverse(int x,int y) { //求x模y的乘法逆元
int flag=0; //记录是否交换x,y
if(x<y) { //令x为较大的那一个
flag=1;
swap(x, y);
}
//以下利用扩展欧几里得算法求乘法逆元
int count=1, s[100], t[100], r[100], q[100];
r[0]=x;
r[1]=y;
s[0]=t[1]=1;
s[1]=t[0]=0;
while(r[count]!=0) { //当余数不为0时
q[count]=r[count-1]/r[count];
s[count+1]=s[count-1]-q[count]*s[count];
t[count+1]=t[count-1]-q[count]*t[count];
count++;
r[count]=r[count-2]%r[count-1];
}
if(flag==1) {
if(t[count-1]<0)
return t[count-1]+x;
else
return t[count-1];
}
else {
if(s[count-1]<0)
return s[count-1]+y;
else
return s[count-1];
}
}
实现中国剩余定理
int main() {
int n; //同余方程的个数
cin>>n; //以下利用中国剩余定理求同余方程组的解
int *b=new int[n],
*m=new int[n],
*a=new int[n], *a_inverse=new int[n];
int mul=1; //模的数的乘积
for(int i=0;i<n;i++) {
cin>>b[i]>>m[i];
mul*=m[i];
}
for(int i=0;i<n;i++) {
a[i]=1;
for(int j=0;j<n;j++) {
if(j==i)
continue;
a[i]*=m[j];
}
a_inverse[i]=inverse(a[i],m[i]); //求乘法逆元
}
int result=0;
for(int i=0;i<n;i++)
result+=a_inverse[i]*a[i]*b[i];
result%=mul;
cout<<"x="<<result<<" (mod "<<mul<<")"<<endl;
return 0;
}
原根和指数
求奇素数原根
//改写求素因子分解的函数,使其记录素因子,并返回素因子个数
int reduceSystem(int n, int *p) { //求缩系
int count=0; //缩系元素个数
for(int i=1;i<n;i++) {
if(gcd(i, n)==1) { //如果互素
p[count]=i;
count++;
}
}
return count;
}
int remain(int a, int n, int m) { //求余数
int r=a%m;
for(int i=1;i<n;i++)
r=(r*a)%m; //依次求余数,而不是直接求余数,避免溢出
return r;
}
int primaryRoot(int m) { //求最小原根
int o=m-1, //欧拉函数
*p=new int[m]; //欧拉函数的素因子
int len=deposition(o, p); //欧拉函数的素因子个数
for(int i=0;i<len;i++)
p[i]=(o/p[i]);
int root=0; //最小原根
for(int i=2;i<m;i++) {
int flag=true; //是否为原根
for(int j=0;j<len;j++) {
if(remain(i,p[j],m)==1) { //与1同余
flag=false; //不是原根
break;
}
}
if(flag) {
root=i;
break; //找到最小原根
}
}
return root;
}
int main() {
int m; //奇素数
cin>>m;
int *r=new int[m-1]; //欧拉函数的缩系
int len=reduceSystem(m-1, r); //欧拉函数缩系的长度
int *result=new int[len]; //奇素数的所有原根
for(int i=0;i<len;i++)
result[i]=remain(primaryRoot(m), r[i], m);
sort(result,result+len); //按照从小到大的顺序排列
for(int i=0;i<len;i++)
cout<<result[i]<<" ";
cout<<endl;
return 0;
}
构造指数表
void index(int m) { //求指数表,m为奇素数
int root=primaryRoot(m), o=m-1;
int *ind=new int[o]; //指数
ind[0]=1;
for(int i=1;i<o;i++)
ind[i]=remain(root, i, o+1);
int **table=new int*[o/10+1]; //指数表
for(int i=0;i<o/10+1;i++)
table[i]=new int[10];
for(int i=0;i<o/10+1;i++)
for(int j=0;j<10;j++)
table[i][j]=-1; //初始化为-1
for(int i=0;i<o;i++) { //入表
int a=ind[i]/10;
int b=ind[i]%10;
table[a][b]=i;
}
//以下是输出格式设置
cout<<setw(5)<<" ";
for(int i=0;i<10;i++)
cout<<setw(5)<<i;
cout<<endl;
for(int i=0;i<o/10+1;i++){
cout<<setw(5)<<i;
for(int j=0;j<10;j++){
if(table[i][j]==-1)
cout<<setw(5)<<" ";
else
cout<<setw(5)<<table[i][j];
}
cout<<endl;
}
}