PAT之基础复习

🍔基础数学

进制转换🥖

对于P进制的数,转换为Q进制:先将P进制转换为10进制,然后由10进制转换为Q进制。

P进制x转10进制y:

    int P,x;
    cin>>x>>P;
    int y=0,product=1;
    while(x!=0){
        y+=(x%10)*product;
        x/=10;
        product*=P;
    }

10进制y转Q进制z:(数组z中从高位到低位即为答案)

    int z[40],num=0,Q;
    cin>>Q;
    do{
        z[num++]=y%Q;
        y/=Q;
    }while(y!=0);

快速幂🌯

typedef long long LL;
LL binaryPow(LL a,LL b,LL m){
    if(b==0) return 1;
    if(b&1) return a*binaryPow(a,b-1,m)%m;
    else{
        LL mul=binaryPow(a,b/2,m);
        return mul*mul%m;
    }
}

最大公约数(gcd)与最小公倍数(lcm)🍖

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

关于gcd(a,b),算法文件中有个函数__gcd(a,b),可直接使用

int lcm(int a,int b){
    int d=gcd(a,b);
    return a/d*b;//防溢出
}

分数的运算🍢

初始:

struct Fraction{
    long long up,down;
}

化简:

Fraction reduction(Fraction result){
    if(result.down<0){
        result.up=-result.up;
        result.down=-result.down;
    }
    if(result.up==0){
        result.down=1;
    }else{
        int d=gcd(abs(result.up),abs(result.down));
        result.up/=d;
        result.down/=d;
    }
    return result;
}

加法:

Fraction add(Fraction f1,Fraction f2){
    Fraction result;
    result.up=f1.up*f2.down+f2.up*f1.down;
    result.down=f1.down*f2.down;
    return reduction(result);
}

减法:

Fraction minu(Fraction f1,Fraction f2){
    Fraction result;
    result.up=f1.up*f2.down-f2.up*f1.down;
    result.down=f1.down*f2.down;
    return reduction(result);
}

乘法:

Fraction multi(Fraction f1,Fraction f2){
    Fraction result;
    result.up=f1.up*f2.up;
    result.down=f1.down*f2.down;
    return reduction(result);
}

除法:

Fraction divide(Fraction f1,Fraction f2){
    Fraction result;
    result.up=f1.up*f2.down;
    result.down=f2.up*f1.down;
    return reduction(result);
}

输出:

void showFraction(Fraction f){
    f=reduction(f);
    if(f.down==1) printf("%lld",f.up);
    else if(abs(f.up)>f.down){
        printf("%d %d/%d",f.up/f.down,abs(f.up)%f.down,f.down);
    }
}

素数🍭

bool isPrime(int n){
    if(n<=1) return false;
    for(int i=2;i*i<=n;++i){
        if(n%i==0) return false;
    }
    return true;
}

质因子分解🍡

对于int大小的数,fac数组只需要开到10.

struct factor{
    int x,cnt;//x为质因子,cnt为个数
}fac[10];

大整数运算🍾

初始:

struct bign{
    int d[1000];
    int len;
    bign(){
        memset(d,0,sizeof(d));
        len=0;
    }
};

字符串转bign:

bign change(char str[]){
    bign a;
    a.len=strlen(str);
    for(int i=0;i<a.len;++i){
        a.d[i]=str[a.len-i-1]-'0';
    }
    return a;
}

比较大小:

int compare(bign a,bign b){
    if(a.len>b.len) return 1;
    else if(a.len<b.len) return -1;
    for(int i=a.len-1;i>=0;--i){
        if(a.d[i]>b.d[i]) return 1;
        else if(a.d[i]<b.d[i]) return -1;
    }
    return 0;
}

加法:

bign add(bign a,bign b){
    bign c;
    int carry=0;
    for(int i=0;i<a.len||i<b.len;++i){
        int temp=a.d[i]+b.d[i]+carry;
        c.d[c.len++]=temp%10;
        carry=temp/10;
    }
    if(carry!=0){
        c.d[c.len++]=carry;
    }
    return c;
}

减法:

bign sub(bign a,bign b){
    bign c;
    for(int i=0;i<a.len||i<b.len;++i){
        if(a.d[i]<b.d[i]){
            a.d[i+1]--;
            a.d[i]+=10;
        }
        c.d[c.len++]=a.d[i]-b.d[i];
    }
    while(c.len-1>=1&&c.d[c.len-1]==0){C++
        c.len--;
    }
    return c;
}

乘法:

bign multi(bign a,int b){
    bign c;
    int carry=0;
    for(int i=0;i<a.len;++i){
        int temp=a.d[i]*b+carry;
        c.d[c.len++]=temp%10;
        carry=temp/10;
    }
    while(carry!=0){
        c.d[c.len++]=carry%10;
        carry/=10;
    }
    return c;
}

除法:

bign divide(bign a,int b,int&r){
    bign c;
    c.len=a.len;
    for(int i=a.len-1;i>=0;--i){
        r=r*10+a.d[i];
        if(r<b) c.d[i]=0;
        else{
            c.d[i]=r/b;
            r%=b;
        }
    }
    while(c.len-1>=1&&c.d[c.len-1]==0){
        c.len--;
    }
    return c;
}

扩展的欧几里得算法🥄

ax+by=gcd(a,b)

int exGcd(int a,int b,int&x,int&y){
    if(b==0){
        x=1;
        y=0;
        return a;
    }
    int g=exGcd(b,a%b,x,y);
    int temp=x;
    x=y;
    y=temp-a/b*y;
    return g;
}

组合数🥓

long long res[67][67]={0};
long long C(long long n,long long m){
    if(m==0||m==n) return 1;
    if(res[n][m]!=0) return res[n][m];
    return res[n][m]=C(n-1,m)+C(n-1,m-1);
}

🍟排序

选择排序

每次选出一个最小的进行排序(基本不考)

插入排序🌯

每次指针向后移一位新加入一个data,对新加入的这个data前重新进行排序。(A1089和A1098有考,写代码的时候可以凑巧使用sort函数)

归并排序🍗

一般是二路归并排序:两两分组,排序后再次两两分组,最后只剩下一个组

const int maxn=100;
void merge(int a[],int l1,int r1,int l2,int r2){
    int i=l1,j=l2;
    int temp[maxn],index=0;
    while(i<=r1&&j<=r2){
        if(a[i]<=a[j]){
            temp[index++]=a[i++];
        }else{
            temp[index++]=a[j++];
        }
    }
    while(i<=r1) temp[index++]=a[i++];
    while(j<=r2) temp[index++]=a[j++];
    for(i=0;i<index;++i){
        a[l1+i]=temp[i];
    }
}
void mergeSort(int a[],int left,int right){
    if(left<right){
        int mid=(left+right)/2;
        mergeSort(a,left,mid);
        mergeSort(a,mid+1,right);
        merge(a,left,mid,mid+1,right);
    }
}

快速排序🍡

int partition(int a[],int left,int right){
    int temp=a[left];
    while(left<right){
        while(left<right&&a[right]>temp) --right;
        a[left]=a[right];
        while(left<right&&a[left]<=temp) ++left;
        a[right]=a[left];
    }
    a[left]=temp;
    return left;
}
void quickSort(int a[],int left,int right){
    if(left<right){
        int pos=partition(a,left,right);
        quickSort(a,left,pos-1);
        quickSort(a,pos+1,right);
    }
}

堆排序🍷

const int maxn=1005;
int heap[maxn],n;
void downAdjust(int low,int high){
    int i=low,j=2*i;
    while(j<=high){
        if(j+1<high&&heap[j+1]>heap[j]) ++j;
        if(heap[j]>heap[i]){
            swap(heap[j],heap[i]);
            i=j;
            j=2*i;
        }else break;
    }
}
void heapSort(){
    for(int i=n/2;i>=1;--i){
        downAdjust(i,n);
    }
    for(int i=n;i>1;--i){
        swap(heap[i],heap[1]);
        downAdjust(1,i-1);
    }
}

二分查找🍭

对一个有序数组,每次查找时,取中间的位置。

注意:这个数组的数据有可能是有重复的,具体需要注意题目的要求。

下面是二分查找的有重数组的第一个x:

int lower_bound(int a[],int left,int right,int x){
    int mid;
    while(left<right){
        mid=(right-left)/2+left;
        if(a[mid]>=x) right=mid;
        else left=mid+1;
    }
    return left;
}

🍳散列

普通散列法

比如名字或者一个字符串,将其中每个字母分别对应于一个数字,然后相加,成为对应的hash值。

除留余数法(Division by remainder)

hash(key)=key%mod

这个没考过。。。

线性探查法(Linear Probing)

如果对应的hash(key)已经被占用,那么就选择hash(key)+1,依次进行判断,直到第一个未被占用

平方探查法(Quadratic probing)🦁

当has(key)被占用时,探查hash(key)+12,hash(key)-12,hash(key)+22,hash(key)-22……

如果超出了表TSize的范围,那么就取模TSize

这个方法是个重点。

链地址法(拉链法)

posted @ 2020-09-04 20:07  sszz_w  阅读(115)  评论(0编辑  收藏  举报