您的位置:首页 > 其它

NOIP 考前模板整理

2013-11-01 21:35 211 查看
0. 去掉最后的syetem("pause");!!!!

1. 头文件一定要加,快排swap在algorithm 注意memset()要cstring

2. 变量名称一定要独特,firstnexty1,biao,tm,都不可以用!!!

3. return 0一定要打上不要手懒。

4. long long在NOIP用lld读,  doublelf读入用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)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: