NOIP考试技巧及注意事项&&信息学竞赛常用函数/模板

[NOIP提高组(2018)考试技巧及注意事项] (https://blog.csdn.net/hi_ker/article/details/81181615)
1.保持好的心态
2.审题
3.考虑严谨
4.代码正确
5.freopen
6.检查
还有注意检查你的程序是否在考试指定文件夹里面,而且不能存在指定文件夹的子文件夹里面

7.防爆(防止爆数组)
8.头文件
9.数据类型
10.增加程序的鲁棒性(Robust)
11.注意隐性错误(非常重要)
以下讨论主要是基于windows考试环境
1.时间复杂度的选择
2.利用Dev C++
3.对拍
4.巧用cmd(选学)
5.查错
6.骗分
[信息学竞赛常用函数/模板] (https://blog.csdn.net/Hi_KER/article/details/82973124)
扩展欧几里得算法
void exgcd(int a,int b,int& d,int& x,int& y){
    if(!b){d=a,x=1,y=0;return;}
    exgcd(b,a%b,d,y,x);y-=x*(a/b);
}
1
2
3
4
乘法逆元
void exgcd(int a,int b,int& d,int& x,int& y){
    if(!b){d=a,x=1,y=0;return;}
    exgcd(b,a%b,d,y,x);y-=x*(a/b);
}
int inverse(int a,int m){
    int x,y,d;
    exgcd(a,m,d,x,y);
    return d==1?(x%m+m)%m:-1;
}

1
2
3
4
5
6
7
8
9
10
高精度模板
https://blog.csdn.net/Hi_KER/article/details/80982710

O(N−−√) O(\sqrt {N})O( 
N
​    
 )计算欧拉函数
int phi(int x){
    int ans=x,m=sqrt(x+0.01);
    for(int i=2;i<=m;i++) if(x%i==0){
        ans=ans/i*(i-1);
        while(x%i==0) x/=i;
    }
    if(x>1) ans=ans/x*(x-1);//x为质数
    return ans;
}

1
2
3
4
5
6
7
8
9
10
线性时间复杂度生成欧拉函数表+质数表
/* 
p|n &&  p*p|n phi(n)=phi(n/p)*p
p|n && !p*p|n phi(n)=phi(n/p)*(p-1) 
*/ 
int v[maxn],pri[maxn],phi[maxn];
void eular(int n){
    int num=0;//number of prime 
    for(int i=2;i<=n;i++) {
        if(v[i]==0){//v[i]:i 的最小质因子
            v[i]=i,pri[++num]=i;
            phi[i]=i-1;
        }
        for(int j=1;j<=num;j++){
            if(pri[j]>v[i]||pri[j]>n/i) break;
            v[i*pri[j]]=pri[j];
            phi[i*pri[j]]=phi[i]*(i%pri[j]?pri[j]-1:pri[j]);
        }
    }
    for(int i=1;i<=n;i++) printf("phi(%d)=%d\n",i,phi[i]);
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
BSGS算法(说明:用于计算高次同余方程 ax≡b (mod p) a ^ x \equiv b\ (mod\ p)a 
x
 ≡b (mod p) 的最小非负数解,其中p pp为素数,时间复杂度O(P−−√) O(\sqrt{P} )O( 
P
​    
 ),返回−1 -1−1表示无解)
int pow_mod(int a,int n,int p){
    int ret=1;
    while(n){
        if(n&1) ret=(long long)ret*a%p;
        a=(long long)a*a%p,n>>=1;
    }
    return ret;
}
map<int,int>mp;
int bsgs(int a,int b,int p){
    if(a%p==0) return b?-1:0;
    mp.clear();
    int m=ceil(sqrt(p)),T=b%p;
    mp[T]=0;
    for(int i=1;i<=m;i++)
        mp[T=(long long)T*a%p]=i;
    int t=pow_mod(a,m,p);T=1;
    for(int i=1;i<=m;i++){
        T=(long long)T*t%p;
        if(mp.count(T)) return i*m-mp[T];
    }
    return -1;
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
卢卡斯(Lucas)定理
int C(int N,int M,int p){
    if(N<M) return 0;
    if(!n) return 1;
    return (ll)fac[N]*inv[M]*inv[N-M]%p;
}
int lucas(int N,int M,int p){
    if(M==0) return 1;
    return (ll)lucas(N/p,M/p,p)*C(N%p,M%p,p)%p;
}

1
2
3
4
5
6
7
8
9
10
扩展中国剩余定理
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=100005;
#define ll __int128
void exgcd(ll a,ll b,ll& d,ll& x,ll& y){
    if(!b){x=1,y=0,d=a;return;}
    exgcd(b,a%b,d,y,x),y-=x*(a/b);
}
ll gcd(ll a,ll b){
    return b?gcd(b,a%b):a;
}
ll lcm(ll a,ll b){
    return a*b/gcd(a,b);
}
ll a[maxn],b[maxn];
long long a__,b__;
int n;
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++) 
        scanf("%lld%lld",&a__,&b__),a[i]=a__,b[i]=b__;
    for(int i=1;i<n;i++){
        ll a_=a[i],b_=-a[i+1],c_=b[i+1]-b[i],d,x,y,md;
        exgcd(a_,b_,d,x,y);
        if(c_%d){break;/*No answer*/}
        x=c_/d*x,md=b_/d;
        if(md<0) md=-md;
        x=(x%md+md)%md;
        b[i+1]=a[i]*x+b[i];
        a[i+1]=lcm(a[i],a[i+1]);
    }
    printf("%lld\n",(long long)b[n]);
    return 0;
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
矩阵运算
struct matrix{
    #define T int
    #define MOD 0x7fffffff
    int N,M;
    T mtx[maxn][maxn];
    matrix(){M=N=0;memset(mtx,0,sizeof(mtx));}
    void resize(int n,int m){N=n,M=m;}
    void unit_matrix(int n){
        memset(mtx,0,sizeof(mtx));
        N=M=n;
        for(int i=0;i<n;i++) mtx[i][i]=1;
    }
    void input(){//just for int
        for(int i=0;i<N;i++)
          for(int j=0;j<M;j++)
            scanf("%d",&mtx[i][j]);
    }
    void output(){//just for int
        for(int i=0;i<M;i++){
            for(int j=0;j<N;j++)
                printf("%d ",mtx[i][j]);
            putchar('\n');
        }
    }
    friend matrix operator * (matrix x,matrix y){
        matrix ans;
        if(x.N!=y.M) return ans; //Error
        ans.N=x.N,ans.M=y.M;
        for(int i=0;i<x.N;i++)
          for(int j=0;j<y.M;j++){
            T S=0;
            for(int k=0;k<x.N;k++)
                S=(S+x.mtx[i][k]*y.mtx[k][j])%MOD;
            ans.mtx[i][j]=S%MOD;
        }
        return ans;
    }
    friend matrix operator ^ (matrix x,int n){
        matrix ans;
        if(x.N!=x.M) return ans;//Error
        ans.unit_matrix(x.N);
        while(n){
            if(n&1) ans=ans*x;
            x=x*x,n>>=1;
        }
        return ans;
    }
    #undef T
    #undef MOD
};

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
数据结构模块

并查集
struct union_set{
    int f[maxn];
    void init(int n){for(int i=1;i<=n;i++) f[i]=i;}
    int find(int x){return x==f[x]?x:f[x]=find(f[x]);}
    bool merge(int x,int y){
        int fx=find(x),fy=find(y);
        if(fx!=fy) f[fx]=fy;
        return fx==fy;
    }
};

1
2
3
4
5
6
7
8
9
10
11
链表 (数组版)
struct node{
    int v,pre,nxt;
};
struct link_list{
    node E[maxn];
    int now,head,tail;
    link_list(){
        now=2,head=1,tail=2;
        E[head].nxt=tail,E[tail].pre=head;
    }
    int insert(int pos,int v){
        now++,E[now].v=v;
        E[E[pos].nxt].pre=now,E[now].nxt=E[pos].nxt;
        E[pos].nxt=now,E[now].pre=pos;
        return now;
    }
    int insert_to_tail(int v){
        return insert(E[tail].pre,v);
    }
    void del(int pos){
        E[E[pos].pre].nxt=E[pos].nxt;
        E[E[pos].nxt].pre=E[pos].pre;
    }
};

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
指针加强版
二叉堆(说明:比起优先队列,多了一个remove操作)
template<typename T>
class Heap{
  private:
    T heap[maxn];
    int now;
  public:
    Heap(){now=0;}
    void up(int p){
        while(p){
          if(heap[p]<heap[p/2])
            swap(heap[p],heap[p/2]),p/=2;
          else break;
        }
    }
    void down(int p){
        int p_=p*2;
        while(p_<=now){
            if(p_<now&&heap[p_+1]<heap[p_]) p_++;
            if(heap[p_]<heap[p])
              swap(heap[p_],heap[p]),p=p_,p_*=2;
            else break;
        }
    }
    void push(T v){heap[++now]=v,up(now);}
    void pop(){heap[1]=heap[now--],down(1);}
    void remove(int p){heap[p]=heap[now--],up(p),down(p);}
    T top(){return heap[1];}
};

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
二维树状数组 (说明:支持单点修改,区间求值)
简易版
struct BIT_2{
  private:
      #define lowbit(x) ((x)&-(x))
    int C[maxn][maxn];
  public:
      void update(int x,int y,int d){
          for(int i=x;i<=n;i+=lowbit(i))
            for(int j=y;j<=m;j+=lowbit(j))
              C[i][j]+=d;
    }
    int query(int x,int y){
        int ret=0;
        for(int i=x;i>0;i-=lowbit(i))
          for(int j=y;j>0;j-=lowbit(j))
            ret+=C[i][j];
        return ret;
    }
};

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
加强版
template<typename T,int N,int M>
class BIT_2{
  private:
      #define lowbit(x) ((x)&-(x))
    T C[N+1][M+1],N_,M_;
  public:
      BIT_2(){N_=N,M_=M;}
      void reset(int n_,int m_){N_=n_,M_=m_;}
      void update(int x,int y,int d){
          for(int i=x;i<=N_;i+=lowbit(i))
            for(int j=y;j<=M_;j+=lowbit(j))
              C[i][j]+=d;
    }
    T query(int x,int y){
        T ret=0;
        for(int i=x;i>0;i-=lowbit(i))
          for(int j=y;j>0;j-=lowbit(j))
            ret+=C[i][j];
        return ret;
    }
    T query(int x,int y,int x_,int y_){
        return query(x_,y_)-query(x-1,y_)-query(x_,y-1)+query(x-1,y-1);
    }
};

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
Splay
Splay实现平衡树
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=100005;
int fa[maxn],ch[maxn][2],val[maxn],cnt[maxn],sz[maxn],rt,now;
int chk(int x){
    return ch[fa[x]][1]==x;
}
#define pushup(x) sz[x]=sz[ch[x][0]]+sz[ch[x][1]]+cnt[x]
void rotate(int x){
    int y=fa[x],z=fa[y],k=chk(x),w=ch[x][k^1];
    ch[y][k]=w,fa[w]=y;
    ch[z][chk(y)]=x,fa[x]=z;
    ch[x][k^1]=y,fa[y]=x;
    pushup(y),pushup(x);
}
void splay(int x,int goal=0){
    while(fa[x]!=goal){
        int y=fa[x],z=fa[y];
        if(z!=goal){
            if(chk(x)==chk(y)) rotate(y);
            else rotate(x);
        }
        rotate(x);
    }
    if(!goal) rt=x;
}
void rebuild(int x){//将小于等于x的最大元素重建到根
    int cur=rt;
    while(ch[cur][x>val[cur]]&&x!=val[cur])
        cur=ch[cur][x>val[cur]];
    splay(cur);
}
void insert(int x){
    int cur=rt,p=0;
    while(cur&&val[cur]!=x)
        p=cur,cur=ch[cur][x>val[cur]];
    if(cur) cnt[cur]++;
    else{
        cur=++now;
        if(p) ch[p][x>val[p]]=cur;
        ch[cur][0]=ch[cur][1]=0;
        val[cur]=x,fa[cur]=p;
        cnt[cur]=sz[cur]=1;
    }
    splay(cur);
}
int rank(int x){
    rebuild(x);
    return sz[ch[rt][0]];
}
int kth(int k){
    int cur=rt;
    while(true){
        if(ch[cur][0]&&k<=sz[ch[cur][0]])
            cur=ch[cur][0];
        else if(k>sz[ch[cur][0]]+cnt[cur])
            k-=sz[ch[cur][0]]+cnt[cur],cur=ch[cur][1];
        else return cur;
    }
}
int beside(int x,int pre){
    rebuild(x);
    if((val[rt]<x&&pre)||(val[rt]>x&&!pre)) return rt;
    int cur=ch[rt][pre^1];
    while(ch[cur][pre]) cur=ch[cur][pre];
    return cur;
}
void remove(int x){
    int pre=beside(x,1),nxt=beside(x,0);
    splay(pre),splay(nxt,pre);
    int cur=ch[nxt][0];
    if(cnt[cur]>1) cnt[cur]--,splay(cur);
    else ch[nxt][0]=0,sz[nxt]--,sz[pre]--;
}
int main(){
    int c,x,m;
    scanf("%d",&m);
    insert(0x3f3f3f3f);
    insert(-0x3f3f3f3f);
    while(m--){
        scanf("%d%d",&c,&x);
        switch(c){
            case 1:insert(x);break;
            case 2:remove(x);break;
            case 3:printf("%d\n",rank(x));break;
            case 4:printf("%d\n",val[kth(x+1)]);break;
            case 5:printf("%d\n",val[beside(x,1)]);break;
            case 6:printf("%d\n",val[beside(x,0)]);break;
        }
    }
    return 0;
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
Splay实现序列翻转
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=100005;
int fa[maxn],ch[maxn][2],val[maxn],cnt[maxn],sz[maxn],rt,now;
int n,m,l,r,rev[maxn];
int chk(int x){
    return ch[fa[x]][1]==x;
}
void pushup(int x){
    sz[x]=sz[ch[x][0]]+sz[ch[x][1]]+cnt[x];
}
void pushdown(int x){
    if(!rev[x]) return;
    swap(ch[x][0],ch[x][1]);
    if(ch[x][0]) rev[ch[x][0]]^=1;
    if(ch[x][1]) rev[ch[x][1]]^=1;
    rev[x]=0;
}
void rotate(int x){
    int y=fa[x],z=fa[y],k=chk(x),w=ch[x][k^1];
    ch[y][k]=w,fa[w]=y;
    ch[z][chk(y)]=x,fa[x]=z;
    ch[x][k^1]=y,fa[y]=x;
    pushup(y),pushup(x);
}
void splay(int x,int goal=0){
    while(fa[x]!=goal){
        int y=fa[x],z=fa[y];
        pushdown(z),pushdown(y),pushdown(x);//在这道题里可以不要 
        if(z!=goal){
            if(chk(x)==chk(y)) rotate(y);
            else rotate(x);
        }
        rotate(x);
    }
    if(!goal) rt=x;
}
void insert(int x){
    int cur=rt,p=0;
    while(cur&&val[cur]!=x)
        p=cur,cur=ch[cur][x>val[cur]];
    if(cur) cnt[cur]++;
    else{
        cur=++now;
        if(p) ch[p][x>val[p]]=cur;
        ch[cur][0]=ch[cur][1]=0;
        val[cur]=x,fa[cur]=p;
        cnt[cur]=sz[cur]=1;
    }
    splay(cur);
}
int kth(int k){
    int cur=rt;
    while(true){
        pushdown(cur);
        if(ch[cur][0]&&k<=sz[ch[cur][0]])
            cur=ch[cur][0];
        else if(k>sz[ch[cur][0]]+cnt[cur])
            k-=sz[ch[cur][0]]+cnt[cur],cur=ch[cur][1];
        else return cur;
    }
}
void reverse(int l,int r){
    int x=kth(l),y=kth(r+2);
    splay(x),splay(y,x);
    rev[ch[y][0]]^=1;
}
void output(int x){
    pushdown(x);
    if(ch[x][0]) output(ch[x][0]);
    if(val[x]&&val[x]<=n) printf("%d ",val[x]);//要判断虚拟节点
    if(ch[x][1]) output(ch[x][1]);
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=0;i<=n+1;i++) insert(i);
    while(m--)
        scanf("%d%d",&l,&r),reverse(l,r);
    output(rt);
    return 0;
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
其他

对拍器
说明:写入记事本,保存为后缀名为.bat .bat.bat的文件,即可执行;其中randdata.exe randdata.exeranddata.exe为数据生成器,code1.exe code1.execode1.exe
code2.exe code2.execode2.exe分别为测试程序与标准程序。

@echo off
for /l %%i in (1,1,100) do (
  randdata.exe > in.txt
  code1.exe < in.txt > out1.txt
  code2.exe < in.txt > out2.txt
  fc out1.txt out2.txt > result.txt
  if errorlevel 1 echo %%i:WA! && pause
  if not errorlevel 1 echo %%i:AC!
)
pause
1
2
3
4
5
6
7
8
9
10
快速输入输出(适用于非负整数)
char in_c;
template<typename T>
void scan(T &in_n){
    for(in_c=getchar();in_c<'0'||in_c>'9';in_c=getchar());
    for(in_n=0;in_c>='0'&&in_c<='9';in_c=getchar()) in_n=in_n*10+in_c-'0';
}
char out_c[25];
int sz_out_c;
template<typename T>
void print(T out_n){
    sz_out_c=0;
    if(!out_n) out_c[sz_out_c++]='0';
    while(out_n) out_c[sz_out_c++]=out_n%10+'0',out_n/=10;
    while(sz_out_c--) putchar(out_c[sz_out_c]);
}
--------------------- 
作者:临渊羡鱼_退而结网 
来源:CSDN 
原文:https://blog.csdn.net/qq_39897867/article/details/83623201 
版权声明:本文为博主原创文章,转载请附上博文链接!

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值