NOIP 考前模板整理
2013-11-01 21:35
211 查看
0. 去掉最后的syetem("pause");!!!!
1. 头文件一定要加,快排swap在algorithm 注意memset()要cstring
2. 变量名称一定要独特,first、next、y1,biao,tm,都不可以用!!!
3. return 0一定要打上不要手懒。
4. long long在NOIP用lld读, double 用lf读入用f输出
5. 并查集查找函数不要用find!
6. long long进行赋值最后加LL
7. 分母上有变量,考虑为0的情况(/和%)
8. 用log变乘为加
9. 用O(N*N)枚举出Y1,Y2,然后考察之间夹的矩形是非常常用的方法。
10. 涉及01串的问题,想到位运算。
11.对于想不出算法的题目,先有序化。
12.很多时候,输入的两个数据并没有给定大小关系。
13. 用(a-b+c) mod c而不是(a-b) mod c
14.最后20分钟一定要检查程序,注意去掉调试,编译,应用文件进行测试。
15.保留所有版本的程序。
16. 初始化问题,不是所有的初始化都设为0,有些需要初始化为负无穷、正无穷(坐标)。
模算数:(注意:一个数%n后的结果在0-n-1之间)
(a+b)mod n = ((a mod n)+(b mod n)) mod n;
(a-b)mod n=((a mod n) - (b mod n) +n) mod n; 注意在减法中,会出现负数,所以要加上n的大小;
(a*b)mod n=(long long)(a mod n) * (b mod n) mod n; 在乘法中,可能会爆int,用long long 存储中间结果
筛欧拉函数
求欧拉函数n
欧几里得、最小公倍数、扩展欧几里得
计算欧拉函数的值
搜索框架
二分答案验证(具体题目具体分析):
筛素数
floyed:
最小生成树之kruscal算法:
dijstra:
邻接矩阵
邻接表+堆优化
SPFA:
vector形式的邻接表实现SPFA(速度极慢):
数组模拟链表实现的SPFA(速度快但是容易出错)
归并排序\求逆序对数
高精度模板
快速幂
并查集
拓扑排序(n^2):
拓扑排序(n+e),邻接表存图+栈:
字符串:
读入一行 getline(cin,s)
读入一个单词 cin>>s
返回‘abcd’在s中的位置: k=s.find("abcd");
返回串长 k=s.length();
复制 s1=s.substr(pos,n);
插入 s1.insert(pos,"内容");
删除 s1.erase(pos,n);
判断是否为空 s.empty()
取消cin\cout同步:
ios::sync_with_stdio(false);
下一个排列: next_permutation(a+1,a+1+n);
当对long long 变量赋值时,后要加LL
Long long x=6327844632743269843LL
字母树
树状数组
卡特兰数
令h(0)=1,h(1)=1,卡塔兰数数满足递归式:
h(n)= h(0)*h(n-1) + h(1)*h(n-2) + ... + h(n-1)h(0) (其中n>=2),这是n阶递推关系;
还可以化简为1阶递推关系: 如h(n)=(4n-2)/(n+1)*h(n-1)(n>1) h(0)=1
该递推关系的解为:h(n)=C(2n,n)/(n+1)=P(2n,n)/(n+1)!=(2n)!/(n!*(n+1)!) (n=1,2,3,...)
卡 塔兰数例的前几项为(sequence A 0 0 0 1 0 8 in OEIS) [注: n = 0, 1, 2, 3, … n]
1, 1, 2, 5, 14, 42, 132, 429, 1430, 4862, 16796, 58786, 208012, 742900, 2674440, 9694845, 35357670, 129644790, 477638700, 1767263190, 6564120420, 24466267020, 91482563640, 343059613650, 1289904147324, 4861946401452, …
斐波那契数列:
f(n)=f(n-1)+f(n-2);
gcd(f(n),f(m))=f(gcd(n,m)) 0、1、1、2、3、5、8、13、21
组合数
c(n,m)=c(n-1,m-1)+c(n-1,m)
1. 头文件一定要加,快排swap在algorithm 注意memset()要cstring
2. 变量名称一定要独特,first、next、y1,biao,tm,都不可以用!!!
3. return 0一定要打上不要手懒。
4. long long在NOIP用lld读, double 用lf读入用f输出
5. 并查集查找函数不要用find!
6. long long进行赋值最后加LL
7. 分母上有变量,考虑为0的情况(/和%)
8. 用log变乘为加
9. 用O(N*N)枚举出Y1,Y2,然后考察之间夹的矩形是非常常用的方法。
10. 涉及01串的问题,想到位运算。
11.对于想不出算法的题目,先有序化。
12.很多时候,输入的两个数据并没有给定大小关系。
13. 用(a-b+c) mod c而不是(a-b) mod c
14.最后20分钟一定要检查程序,注意去掉调试,编译,应用文件进行测试。
15.保留所有版本的程序。
16. 初始化问题,不是所有的初始化都设为0,有些需要初始化为负无穷、正无穷(坐标)。
模算数:(注意:一个数%n后的结果在0-n-1之间)
(a+b)mod n = ((a mod n)+(b mod n)) mod n;
(a-b)mod n=((a mod n) - (b mod n) +n) mod n; 注意在减法中,会出现负数,所以要加上n的大小;
(a*b)mod n=(long long)(a mod n) * (b mod n) mod n; 在乘法中,可能会爆int,用long long 存储中间结果
筛欧拉函数
memset(phi,0,sizeof(phi)); phi[1] = 1; for(int i = 2; i < N; i++) if(!phi[i]) { for(int j = i; j < N; j+=i) { if(!phi[j]) phi[j] = j; phi[j] = phi[j] / i * (i-1); } }
求欧拉函数n
int oula(int n) { int m =(int)floor(sqrt(n+0.5)); int ans = n; for(int i = 2; i <= m; i++) if(n%i == 0) { ans = ans / i * (i-1); while(n%i == 0) { n /= i; } } if(n > 1) ans = ans / n *(n-1); return ans; }
欧几里得、最小公倍数、扩展欧几里得
int gcd(int a,int b) { return b==0?a:gcd(b,a%b); } int lcm(int a,int b) { return a/gcd(a,b)*b; } void gcd(int a,int b,int &d,int &x,int &y) { if(!b) x=1,y=0,d=a; else gcd(b,a%b,d,y,x),y-=a/b*x; }
计算欧拉函数的值
int OuLa(int n) { int i; int ans; ans=1; for(i=2;i*i<=n;i++) { if(n%i==0) { ans*=(i-1); n/=i; while(n%i==0) { ans*=i; n/=i; } } } if(n!=1)ans*=n-1; return ans; }
搜索框架
void dfs(int c) { if(可以剪枝)break; if(符合条件) { 输出; break; } for(按规则扩展节点) { 改变状态; dfs(c+1); 回溯; } } void bfs() { 初始节点入队; while(q.size()) { 出队; for(按规则扩展节点) { 标记; if(符合条件) { 输出; break; } } } }
二分答案验证(具体题目具体分析):
int x,y; while(x<=y) { int m=(x+y)>>1; if(中间值符合条件){x=m+1;更新ans位置;} else y=m-1; }
筛素数
#include<cmath> bool vis[maxn]; void prime() { vis[1]=1; int m=(int)sqrt(maxn+0.5); for(int i=2;i<=m;i++)if(!vis[i]) for(int j=i*i;j<=50000000;j+=i) vis[j]=1; }
floyed:
void floey() { for(int k=1;k<=n;k++) for(int i=1;i<=n;i++) if(k!=i) for(int j=1;j<=n;j++) if(k!=j&&i!=j) if(a[i][k]+a[k][j]<a[i][j]) a[i][j]=a[i][k]+a[k][j]; }
最小生成树之kruscal算法:
int find(int i) { return f[i]==i?i:f[i]=find(f[i]); } struct node { int x,y,w; bool operator < (node tmp) const { return w<tmp.w; } }a[maxm]; void kruscal() { sort(a+1,a+1+maxm); int ct=0; for(int i=1;i<=maxm;i++) { int p=find(a[i].x); int q=find(a[i].y); if(p!=q) { f[q]=p; ans+=a[i].w; ct++; if(ct==n-1)break; } } }
dijstra:
邻接矩阵
int map[maxn][maxn]; bool vis[maxn]; int d[maxn]; int f[maxn]; //记录路径 void dijstrea(int x) { for(int i=1;i<=n;i++)d[i]=INF; d[x]=0;vis[x]=1; for(int i=1;i<=n;i++) { int MIN=INF,id; for(int j=1;j<=n;j++)if(!visit[j]&&d[j]<MIN)MIN=d[j],id=j; vis[id]=1; for(int j=1;j<=n;j++) { if(d[j]>d[id]+map[id][j]) { d[j]>d[id]+map[id][j]; f[j]=id; //记录路径 } } } }
邻接表+堆优化
#include<queue> using namespace std; struct node { int d,i; bool operator < (node tmp) const { return d>tmp.d; } }; priority_queue<node>q; int first[maxn],next[maxM],u[maxM],v[maxM],w[maxM]; bool vis[maxn]; int d[maxn]; int f[maxn]; //记录路径 void dijstrea(int x) { for(int i=1;i<=n;i++)d[i]=INF; node tmp;tmp.d=d[x];tmp.i=x; q.push(tmp); while(!q.empty()) { node now=q.top(); q.pop(); int x=now.i; if(vis[x])continue; vis[x]=1; for(int e=first[x];e!=-1;e=next[e]) { if(d[v[e]]>d[x]+w[e]) { d[v[e]]=d[x]+w[e]; f[v[e]]=x; tmp kk;kk.d=d[v[e]];kk.i=v[e]; q.push(kk); } } } } void init() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++)first[i]=-1; for(int e=1;e<=m;e++) { scanf("%d%d%d",&u[e],&v[e],&w[e]); next[e]=first[u[e]]; first[u[e]]=e; } }
SPFA:
适用条件&范围 l 单源最短路径(从源点s到其它所有顶点v); l 有向图&无向图(无向图可以看作(u,v),(v,u)同属于边集E的有向图); l 边权可正可负(如有负权回路输出错误提示);
vector形式的邻接表实现SPFA(速度极慢):
#include<queue> #include<vector> struct node { int v,w; }; queue<int>q; vector<node>a[maxn]; int d[maxn]; bool vis[maxn]; void spfa(int x) { for(int i=1;i<=maxn;i++)d[i]=INF; d[x]=0; vis[x]=1; q.push(1); while(q.size()) { int u=q.front(); q.pop(); vis[u]=0; for(int i=0;i<a[u].size();i++) { int v=a[u][i].v,w=a[u][i].w; if(d[u]!=INF&&d[v]>d[u]+w) { d[v]=d[u]+w; if(!vis[v]) { vis[v]=1; q.push(v); } } } } }
数组模拟链表实现的SPFA(速度快但是容易出错)
#include<queue> const int maxn=1000, int maxm=500000, int INF=999999999; int n,m,nxt[maxm*2],fir[maxn],u[maxm*2],v[maxm*2],w[maxm*2]; bool vis[maxn];int d[maxn]; int ct; queue<int>q; void spfa(int x) { for(int i=1;i<=n;i++)d[i]=INF; d[x]=0; q.push(x); vis[x]=1; while(q.size()) { int uu=q.front(); q.pop(); vis[uu]=0; for(int i=fir[uu];i!=-1;i=next[i]) { int vv=v[i],ww=w[i]; if(d[uu]!=INF&&d[vv]>d[uu]+ww) { d[vv]=d[uu]+ww; if(!vis[vv]) { vis[vv]=1; q.push(vv); } } } } } void init() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++)fir[i]=-1; for(int i=1,su,sv,sw;i<=m;i++) { scanf("%d%d%d",&su,&sv,&sw); ct++; u[ct]=su;v[ct]=sv;w[ct]=sw; nxt[ct]=fir[u[ct]]; fir[u[ct]]=ct; ct++; u[ct]=sv;v[ct]=su;w[ct]=sw; nxt[ct]=fir[u[ct]]; fir[u[ct]]=ct; } spfa(1); for(int i=1;i<=n;i++) printf("%d ",d[i]); }
归并排序\求逆序对数
#include<cstdio> #include<iostream> using namespace std; int a[maxn];t[maxn]; void gsort(int *a,int x,int y,int *t) { if(y-x>1) { int m=(x+y)>>1; int p=x,q=m,i=x; gsort(a,x,m,t); gsort(a,m,y,t); while(p<m||q<y) { if(q>=y||(p<m&&a[p]<=a[q])) t[i++]=a[p++]; else { t[i++]=a[q++]; ans+=m-p; //求逆序对数 } } for(i=x;i<y;i++)a[i]=t[i]; } }
高精度模板
#include<cstdio> #include<iostream> #include<algorithm> #include<string.h> using namespace std; const int M=10,P=1; struct BigNum { int n[5000],l,Y; BigNum(){l=1,memset(n,0,sizeof(n));} //---------------------------------- void init() { string s; cin>>s; int now=0,ct=0,c1=1; for(int i=s.length()-1;i>=0;i--) { n[now]+=(s[i]-'0')*c1; c1*=10; ct++; if(ct==P&&i!=0) { now++; c1=1; ct=0; } } l=now+1; } //----------------------------------- void print() { printf("%d",n[l-1]); for(int i=l-2;i>=0;i--) printf("%0*d",P,n[i]); printf("\n"); } //------------------------------------ BigNum operator +(BigNum x)const { BigNum t=*this; if(x.l>t.l)t.l=x.l; for(int i=0;i<t.l;i++) { t.n[i]+=x.n[i]; if(t.n[i]>=M) { t.n[i+1]+=t.n[i]/M; t.n[i]%=M; } } while(t.n[t.l]) { t.n[t.l+1]+=t.n[t.l]/M; t.n[t.l++]%=M; } return t; } //-------------------------------------- bool operator < (BigNum x) const { BigNum t=*this; if(t.l!=x.l)return t.l<x.l; for(int i=t.l-1;i>=0;i--) { if(t.n[i]!=x.n[i])return t.n[i]<x.n[i]; } return 0; } BigNum operator -(BigNum x)const { BigNum t=*this; if(t<x){printf("-");swap(t,x);} for(int i=0;i<t.l;i++) { t.n[i]-=x.n[i]; if(t.n[i]<0) { t.n[i]+=M; --t.n[i+1]; } } while(!t.n[t.l-1]&&t.l>1)t.l--; return t; } //-------------------------------------------- BigNum operator * (BigNum x) const { BigNum c,t=*this; c.l=t.l+x.l-1; for(int i=0;i<t.l;i++) for(int j=0;j<x.l;j++) { c.n[i+j]+=t.n[i]*x.n[j]; if(c.n[i+j]>=M) { c.n[i+j+1]+=c.n[i+j]/M; c.n[i+j]%=M; } } while(c.n[c.l]) { c.n[c.l+1]+=c.n[c.l]/M; c.n[c.l++]%=M; } return c; } BigNum operator * (int x) const { BigNum t=*this,c; c.l=t.l; for(int i=0;i<t.l;i++) { c.n[i]+=t.n[i]*x; if(c.n[i]>=M) { c.n[i+1]+=c.n[i]/M; c.n[i]%=M; } } while(c.n[c.l]) { c.n[c.l+1]+=c.n[c.l]/M; c.n[c.l++]%=M; } return c; } //-------------------------------------------- void Add(int x){if(x||l)n[l++]=x;} void Re(){reverse(n,n+l);} BigNum operator /(const BigNum &x)const { BigNum t=*this,r,y; y.l=0,r.l=t.l; for(int i=t.l-1;i>=0;--i) { y.Add(t.n[i]); y.Re(); while(!(y<x))y=y-x,r.n[i]++; while(!y.n[y.l-1] && y.l>1)--y.l; y.Re(); } while(!r.n[r.l-1] && r.l>1)--r.l; return r; } BigNum operator /(const int &x)const { BigNum t=*this,r; r.l=t.l; int tmp=0; for(int i=t.l-1;i>=0;--i) { tmp+=t.n[i]; if(tmp>=x) r.n[i]+=tmp/x,tmp%=x; tmp*=M; } while(!r.n[r.l-1] && r.l>1)--r.l; return r; } //--------------------------------------- int operator % (int x) const { BigNum t=*this;int ans=0; for(int i=t.l-1;i>=0;i--) ans=(int)( ((long long)ans*10+t.n[i]) % x); return ans; } };
快速幂
int power(int a,int b) { int r=1; while(b) { if(b&1)r*=a; a*=a; b>>=1; } return r; }
并查集
int findfather(int i) { return f[i]==i?i:f[i]=find(f[i]); } int findfather(int i) { if(f[i]==i) return i; else return f[i]=find(f[i]); } int findfather(int i) { if(f[i]==i) { return i; } else { int tmp=find(f[i]); quan[i]+=quan[f[i]]; //权值更新 return f[i]=tmp; } }
拓扑排序(n^2):
const int maxn=1005; int a[maxn][maxn],into[maxn],order[maxn]; void init() { for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) { scanf("%d",&a[i][j]); if(!a[i][j]) into[j]++; } } bool toposort() { for(int i=1;i<=n;i++) { int j; for(j=1;j<=n+1;j++) if(!into[j])break; if(j>n)return 0; into[j]=999999999; order[i]=j; for(int k=1;k<=n;k++) if(a[j][k])into[k]--; } return 1; }
拓扑排序(n+e),邻接表存图+栈:
const int maxn=105, maxm=10005; int fir[maxn],nxt[maxm],u[maxm],v[maxm]; int into[maxn],order[maxn],cnt; int n; stack<int>zhan; bool toposort() { for(int i=1;i<=n;i++) if(!into[i]) zhan.push(i); while(zhan.size()) { int now=zhan.top(); order[++cnt]=now; zhan.pop(); for(int i=fir[now];i!=0;i=nxt[i]) { into[v[i]]--; if(into[v[i]]==0) zhan.push(v[i]); } } return 1; } void init() { scanf("%d",&n); for(int i=1;i<=n;i++)fir[i]=-1; for(int i=1;i<=n;i++) { scanf("%d%d",&u[i],&v[i]); nxt[i]=fir[u[i]]; fir[u[i]]=i; into[v[i]]++; } }
字符串:
读入一行 getline(cin,s)
读入一个单词 cin>>s
返回‘abcd’在s中的位置: k=s.find("abcd");
返回串长 k=s.length();
复制 s1=s.substr(pos,n);
插入 s1.insert(pos,"内容");
删除 s1.erase(pos,n);
判断是否为空 s.empty()
取消cin\cout同步:
ios::sync_with_stdio(false);
下一个排列: next_permutation(a+1,a+1+n);
当对long long 变量赋值时,后要加LL
Long long x=6327844632743269843LL
字母树
struct trie { int ch[1000050][26]; int val[1000050]; int sz; trie(){sz=1;memset(ch,0,sizeof(ch));} int idx(char c) { int tmp=c-'a'; if(tmp<0)tmp+=32; return tmp; } void insert(string s,int v) { int u=0,n=s.length(); for(int i=0;i<n;i++) { int c=idx(s[i]); if(!ch[u][c]) { ch[u][c]=sz++; } u=ch[u][c]; } val[u]=v; } bool find(string s) { int u=0,n=s.length(); for(int i=0;i<n;i++) { int c=idx(s[i]); if(!ch[u][c])return 0; else { u=ch[u][c]; } } if(val[u])return 1;else return 0; } }tree;
树状数组
struct ArrayTree { int lowbit(int i) { return i&(-i); } int findsum(int i) { int sum=0; while(i) { sum+=a[i]; i-=lowbit(i); } return sum; } void insert(int add,int i) { while(i<=n) { a[i]+=add; i+=lowbit(i); } } }a[maxn];
卡特兰数
令h(0)=1,h(1)=1,卡塔兰数数满足递归式:
h(n)= h(0)*h(n-1) + h(1)*h(n-2) + ... + h(n-1)h(0) (其中n>=2),这是n阶递推关系;
还可以化简为1阶递推关系: 如h(n)=(4n-2)/(n+1)*h(n-1)(n>1) h(0)=1
该递推关系的解为:h(n)=C(2n,n)/(n+1)=P(2n,n)/(n+1)!=(2n)!/(n!*(n+1)!) (n=1,2,3,...)
卡 塔兰数例的前几项为(sequence A 0 0 0 1 0 8 in OEIS) [注: n = 0, 1, 2, 3, … n]
1, 1, 2, 5, 14, 42, 132, 429, 1430, 4862, 16796, 58786, 208012, 742900, 2674440, 9694845, 35357670, 129644790, 477638700, 1767263190, 6564120420, 24466267020, 91482563640, 343059613650, 1289904147324, 4861946401452, …
斐波那契数列:
f(n)=f(n-1)+f(n-2);
gcd(f(n),f(m))=f(gcd(n,m)) 0、1、1、2、3、5、8、13、21
组合数
c(n,m)=c(n-1,m-1)+c(n-1,m)
相关文章推荐
- NOIP 模板整理
- NOIP知识汇总及模板整理
- [置顶] NOIP模板整理
- NOIP 前夕 模板整理
- [置顶] NOIP前夕模板整理第二弹:数据结构
- NOIP前模板整理
- NOIP 前夕 模板整理
- NOIP模板整理计划
- 16年NOIP复赛前各种模板的整理
- noip模板整理
- NOIP 模板整理(多图预警╮(╯▽╰)╭)
- [置顶] NOIP前夕模板整理第一弹:图论
- [置顶] NOIP 模板整理计划 NOIP2017 RP++(持续更新中~)
- 中国剩余定理模板(JZOJ 3093. 【NOIP2012模拟11.7】合唱队形)
- noip2017考前整理(未完)
- 【NOIP模板】 trie树
- KMP——模板整理
- NOIP前 基础字符串模板
- graham模板整理
- 三维计算几何模板整理