考试技巧
1.拿到考卷首先通看题目,按自己感觉的难度排序(普及一般是1-2-3-4了~还是相信出题人不会坑我们的2333)
2.一般来说,普及组前两道题比较简单(大水题啊233~),但是通常坑很多,例如NOIP2000计算器的改良一题….非常坑,需要注意1.未知数从A-z中的任意一个字母2.字母系数为1时可以省略….因此要多读3遍题,切记仔细读题,一个字都不能放过。before that think twice and double check you code.(多想几遍然后反复检查代码了~)
3.处理完T1,T2就来到有(ju)趣(ken)的T3了~一般来说普及组的T3 还是挺水的通常思考5~20分钟就能思考出来。然而实现的坑也不比T1,T2。通常T3会让我们进行一些模运算和long long运算。别看这些都这么简单,然而这就是出题老师将100分坑成20分的得力工具啊233~先说long long:在一个运算公式里,要得到long long的结果,一般要让加入运算的所有都开long long(一定要注意是全开long long!!),否则100变50-。再说取模运算:并不是所有的运算都可以乱%的,一定要先判断是否对结果有影响再%,另外记住一点——能%的地方一定不要放过。
4.接着就是T4了,这种题一般都不能得满分的,毕竟还是有难度(像我这种蒟蒻就更做不起了233…),建议是按题目的数据范围一步步优化,尽量拿更高的分数
考试模版
考试专供
随机数据生成器
#include<iostream>
#include<cstdlib>
#include<ctime>
#include<algorithm>
using namespace std;
int num[1000005];
int main()
{
srand(time(NULL));
freopen("begining.out","w",stdout);
int n=(rand()%10000)+1;
printf("%d\n",n);
for(int i=1;i<=n;i++)
{
num[i]=rand()%10000;
}
sort(num+1,num+n+1);
for(int i=1;i<=n;i++)printf("%d ",num[i]);
}
对拍程序
bat版
先新建一个记事本文档;
在文档中写:
@echo off
:loop
begining.exe > data.out
start.exe < data.out > start.out
std.exe < data.out > std.out
fc start.out std.out
if not errorlevel 1 goto loop
pause
goto loop
c++版(推荐)
#include<iostream>
#include<windows.h>
using namespace std;
int main()
{
int testdata=100;
while(1)
{
testdata--;
system("data.exe > data.txt");
system("biaoda.exe < data.txt > biaoda.txt");
system("test.exe < data.txt > test.txt");
if(system("fc test.txt biaoda.txt")) break;
}
if(testdata==0) cout<<"no error"<<endl;
else cout<<"error"<<endl;
system("pause");
return 0;
}
读入优化
int read()
{
int x=0,f=1;char s=getchar();
while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
return x*f;
}
算法——排序
sort版
#include<iostream>
#include<algorithm>
using namespace std;
long long n,a[100000];
int main()
{
scanf("%lld",&n);
for(int i=0;i<n;i++) cin>>a[i];
sort(a,a+n);
for(int i=0;i<n-1;i++) cout<<a[i]<<' ';
cout<<a[n-1];
return 0;
}
快速排序
从小到大
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
int a[100005];
int l,n,m,cont,c;
void quicksort(int x,int y)
{
int l=x,r=y,mid;
mid=a[(l+r)/2];
while(l<=r)
{
while(a[l]<mid)l++;
while(a[r]>mid)r--;
if(l<=r){swap(a[l],a[r]);l++;r--;}
}
if(x<r)quicksort(x,r);
if(y>l)quicksort(l,y);
}
int main()
{
int i;
scanf("%d",&n);
for(i=1;i<=n;i++)scanf("%d",&a[i]);
quicksort(1,n);
for(i=1;i<=n;i++)printf("%d ",a[i]);
}
归并排序
从小到大
#include<iostream>
#include<cstdio>
using namespace std;
int a[100005],s[100005];
long long cont;
void merge(int st,int m,int ov)
{
int l=st,r=m+1,q=0;
while(l<=m&&r<=ov)
{
if(a[l]<=a[r])s[q++]=a[l++];
else {s[q++]=a[r++];cont+=m-l+1;}
}
while(l<=m)s[q++]=a[l++];
while(r<=ov)s[q++]=a[r++];
for(int i=st;i<=ov;i++)a[i]=s[i-st];
}
void mergesort(int st,int ov)
{
if(st<ov)
{
int mid=(st+ov)/2;
mergesort(st,mid);
mergesort(mid+1,ov);
merge(st,mid,ov);
}
}
int main()
{
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
mergesort(1,n);
for(int i=1;i<=n;i++)printf("%d ",a[i]);
printf("\n");
//printf("%lld",cont);//本输出用于求逆序对
}
数据结构
优先队列
#include<queue>
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
priority_queue<int> QAQ;
int n,x,a;
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&x);
if(x==1){scanf("%d",&a);QAQ.push(-a);}
if(x==2)printf("%d\n",-QAQ.top());
if(x==3)QAQ.pop();
}
}
并查集
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int n,m,fa[10005],z,x,y;
int find(int p)
{
if(fa[p]!=p)fa[p]=find(fa[p]);
return fa[p];
}
void bin(int x1,int y1)
{
fa[x1]=y1;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
fa[i]=i;
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&z,&x,&y);
int ta=find(x),tb=find(y);
if(z==1)
{
if(ta==tb)continue;
else bin(ta,tb);
}
if(z==2)
{
if(ta==tb)printf("Y\n");
else printf("N\n");
}
}
}
根据两种遍历顺序确定树结构
#include<cstdio>
#include<iostream>
#include<climits>
#include<algorithm>
#include<queue>
#include<cstring>
using namespace std;
string s1,s2;
void xfind(int len1,int re1,int len2,int re2)
{
int m=s2.find(s1[len1]);
if(m>len2)xfind(len1+1,len1+m-len2,len2,m-1);
if(m<re2)xfind(len1+m-len2+1,re1,m+1,re2);
printf("%c",s1[len1]);
}
int main()
{
cin>>s1>>s2;
xfind(0,s1.length()-1,0,s2.length()-1);
return 0;
}
图论
有向图的DFS
#include<iostream>
#include<algorithm>
#include<climits>
#include<vector>
using namespace std;
struct node
{
int v,next;
}a[20010];
int b[205];
int n,m,maxx,s,num;
bool visit[205];
int read()
{
int x=0,f=1;char s=getchar();
while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
return x*f;
}
void fpush(int from,int to)
{
a[++num].v=to,a[num].next=b[from],b[from]=num;
}
void dfs(int j)
{
visit[j]=1;maxx++;
for(int i=b[j];i;i=a[i].next)
if(visit[a[i].v]==0)dfs(a[i].v);
}
int main()
{
n=read();m=read();
for(int i=1;i<=m;i++)
{
int u,v;
u=read();v=read();
fpush(u,v);
}
s=read();
dfs(s);
printf("%d",maxx);
}
无向图的BFS
#include<iostream>
#include<cstring>
using namespace std;
int n,m,k,head=0,tail=1,a[205],s;
bool b[205],ks[205][205];
int main()
{
memset(b,0,sizeof(b));
memset(a,0,sizeof(a));
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
int u,v;
scanf("%d%d",&u,&v);
ks[u][v]=1;
ks[v][u]=1;
}
scanf("%d",&s);
printf("%d",s);
a[1]=s;
b[s]=1;
while(head!=tail)
{
head++;
int kk=a[head];
for(int i=1;i<=n;i++)
{
if(!b[i]&&ks[kk][i]==1)
{
printf(" %d",i);
tail++;
a[tail]=i;
b[i]=1;
}
}
}
return 0;
}
哈密顿环
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<vector>
using namespace std;
vector<int>a[205];
bool visit[205],flag=1;
int x,n,ans,start=1;
void dfs(int s,int deep)
{
if(deep==n)ans++;
for(int i=0;i<a[s].size();i++)
if(!visit[a[s][i]])
{
visit[a[s][i]]=1;
dfs(a[s][i],deep+1);
visit[a[s][i]]=0;
}
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
scanf("%d",&x);
if(x==1)a[i].push_back(j);
}
for(int i=1;i<=n;i++)
visit[i]=1,dfs(i,1),visit[i]=0;
printf("%d",ans);
}
欧拉回路
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
bool k[105][105],flag=1;
int x,n,du,sum,ff[10005],start=1,p;
void dfs(int s)
{
for(int i=1;i<=n;i++)
if(i!=s&&k[s][i])
{
k[s][i]=0;k[i][s]=0;
dfs(i);
}
ff[++p]=s;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
du=0;
for(int j=1;j<=n;j++)
{
scanf("%d",&x);
if(x==1){k[i][j]=1;du++;}
else k[i][j]=0;
}
if(du%2==1){if(!sum)start=i;sum++;}
}
if(sum>2){printf("No Solution!\n");return 0;}
dfs(start);
printf("%d",ff[p]);
for(int i=p-1;i>=1;i--)printf(" %d",ff[i]);
}
最小生成树
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
struct node
{
int x,y,price;
}a[200005];
int n,m,p,u,v,father[5005],x,y,num,ans,ksum;
bool cmp(node s1,node s2)
{
return s1.price<s2.price;
}
int read()
{
int x=0,f=1;char s=getchar();
while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
return x*f;
}
int find(int p)
{
if(father[p]!=p)father[p]=find(father[p]);
return father[p];
}
void bin(int p1,int p2)
{
father[p2]=p1;
}
int main()
{
n=read();m=read();
for(int i=1;i<=n;i++)bin(i,i);
for(int i=1;i<=m;i++)
u=read(),v=read(),a[++num].price=read(),a[num].x=u,a[num].y=v;
sort(a+1,a+num+1,cmp);
for(int i=1;i<=num;i++)
{
if(ksum==n-1)break;
int s1=find(a[i].x),s2=find(a[i].y);
if(s1!=s2)
{
bin(s1,s2);
ans+=a[i].price;
ksum++;
}
}
if(ksum==n-1)printf("%d\n",ans);
else printf("orz\n");
}
SPFA
#include<cstdio>
#include<queue>
#include<climits>
using namespace std;
int b[10005],vis[10005],now,x,y,z,xnext,cnt,m,n,s,en,d[10005],cont,flag=1;
queue<int>a;
struct node
{
int next,to,w;
}e[500005];
void fpush(int u,int v,int w)
{
e[++cnt].next=b[u];
e[cnt].w=w;
e[cnt].to=v;
b[u]=cnt;
}
void SPFA()
{
a.push(s);
d[s]=0;
while(!a.empty())
{
cont++;
now=a.front();
a.pop();
vis[now]=0;
for(int i=b[now];i;i=e[i].next)
{
xnext=e[i].to;
if(d[now]+e[i].w<d[xnext])
{
d[xnext]=d[now]+e[i].w;
if(!vis[xnext])
{
a.push(xnext);
vis[xnext]=true;
}
}
}
}
}
int main()
{
scanf("%d%d%d",&n,&m,&s);
for(int i=1;i<=n;i++)
d[i]=INT_MAX/2;
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&x,&y,&z);
fpush(x,y,z);
}
SPFA();
for(int i=1;i<=n;i++)
if(d[i]!=INT_MAX/2)printf("%d ",d[i]);
else printf("2147483647 ");
return 0;
}
数论
gcd
int gcd(int m,int n)
{
while(m>0)
{int c=n%m;n=m,m=c;}
return n;
}
线性筛素数
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
int n,m,l,r;
bool isPrime[10000005];
int main()
{
scanf("%d%d",&m,&n);
memset(isPrime,0,sizeof(isPrime));
isPrime[1]=true;
for(int i=2;i<=sqrt(m);i++)
{
if(isPrime[i]==0)
{
for(int j=2*i;j<=m;j+=i)
isPrime[j]=true;
}
}
for(int i=1;i<=n;i++)
{
scanf("%d",&r);
if(!isPrime[r])
printf("Yes\n");
else
printf("No\n");
}
}