清北学堂(2019 5 1) part 4

今天讲数论

1.进制问题(将n转换成k进制数):

  1.方法:短除法

   将n/k,保存,将商当做新的n,将余数保存,直到商为0,将余数(包括0),倒序输出,即得             n的k进制数

2.关于高精四则运算(我本以为不用怎么整的):

   举个加和乘的例子...

  众所周知,a+b problem是最简单的红题,再加个*也无伤大雅,代码如下(没文件头):

int main(){
    int a,b;
    cin>>a>>b;
    cout<<a*b;
    return 0;
}

  直到你加了这些东西:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 struct nu{
 4     int a[100005];
 5     int l;
 6     nu(){
 7         l=1;
 8         memset(a,0,sizeof(a));
 9     }
10     friend istream& operator>>(istream &cin,nu &x){  //意思是:重载>>(用于cin,读到x里面)
11         static char s[100005];
12         cin>>s;
13         int l=strlen(s);
14         for(int i=0;i<=l;i++)
15             x.a[i]=s[l-i-1]-'0';
16         x.l=l;
17         return cin;
18     }
19     friend ostream& operator<<(ostream &cout,const nu &x){   //与上面大同,多了个const,在于使x值在输出前后值相同
20         for(int i=x.l-1;i>=0;i--)
21             cout<<x.a[i];
22     }
23 };
24 nu operator+(const nu &x,const nu &y){    //重载+
25     nu ans;
26     int len=max(x.l,y.l);
27     for(int i=0;i<len;i++)
28         ans.a[i]+=x.a[i]+y.a[i];
29     for(int i=0;i<len;i++){
30         if(ans.a[i]>=10){
31             int now=ans.a[i]/10;
32             ans.a[i+1]+=now;
33             ans.a[i]%=10;
34         }
35         while(ans.a[len+1]) len++;
36     }
37     ans.l=len;
38     return ans;
39 }
40 nu operator*(const nu &x,const nu &y){    //重载*用了非常简单而经典的高精算法
41     nu ans;
42     for(int i=0;i<x.l;i++)
43         for(int j=0;j<y.l;j++)
44             ans.a[i+j]+=x.a[i]*y.a[j];
45     ans.l=x.l+y.l;
46     for(int i=0;i<ans.l;i++){
47         ans.a[i+1]+=ans.a[i]/10;
48         ans.a[i]%=10;
49     }
50     while(ans.l>0&&!(ans.a[ans.l]))
51         ans.l--;
52     ans.l++;
53     return ans;
54 }
55 int main(){
56     nu a,b;
57     cin>>a>>b;
58     cout<<a*b;
59     return 0;
60 }

  6-9行是构造函数,用于memset

  10-22是重载cin与cout,背过就好

  后面一直到主函数之前都是重载运算符

3.关于素数(又是各种筛法)

  粘下模板:

  1.埃氏筛:

#include<bits/stdc++.h>
using namespace std;
bool no[10005]={1,1};
int pri[10000];
int tot;
inline void p(int t){
    for(int i=1;i<=t;i++)
        if(!no[i]){
            pri[++tot]=i;
            for(int j=i+i;j<=t;j+=i)
                no[j]=1;
        }
}
int n;
int main(){
    scanf("%d",&n);
    p(n);
    for(int i=1;i<=tot;i++)printf("%d\n",pri[i]);
    return 0;
}

  欧拉筛(线性筛):

#include<bits/stdc++.h>
using namespace std;
bool no[10005];
int pri[10000];
int tot;
int n;
inline void p(int n){
    for(int i=2;i<=n;i++){
        if(!no[i])
            pri[++tot]=i;
        for(int j=1;j<=n&&i*pri[j]<=n;j++){
            no[i*pri[j]]=1;
            if(!(i%pri[j])) break;
        }
    }
}
int main(){
    scanf("%d",&n);
    p(n);
    for(int i=1;i<=tot;i++)printf("%d\n",pri[i]);
    return 0;
}

  3.exgcd:

#include<bits/stdc++.h>
using namespace std;
int a,b,x,y;
inline int exgcd(int a,int b,int &x,int &y){      //利用性质gcd(a,b)=gcd(b,a%b)
    if(!b){
        x=1;
        y=0;
        return a;
    }int g=exgcd(b,a%b,x,y);
    int t=x;
    x=y;
    y=(t-(a/b)*x);
    return g;
}
int main(){
    cin>>a>>b;
    exgcd(a,b,x,y);
    if(x<0) x+=b;
    cout<<x;
    return 0;
}

  练多了不解释...

  下午考试了..我..应该..大概不会爆零

猜你喜欢

转载自www.cnblogs.com/648-233/p/10800009.html
今日推荐