博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
2014-10-4 NOIP模拟赛
阅读量:4957 次
发布时间:2019-06-12

本文共 9658 字,大约阅读时间需要 32 分钟。

1、某种密码(password.*)

    关于某种密码有如下描述:某种密码的原文A是由N个数字组成,而密文B是一个长度为N的01数串,原文和密文的关联在于一个钥匙码KEY。若KEY=∑▒〖Ai*Bi〗,则密文就是原文的一组合法密码。

    现在有原文和钥匙码,请编一个程序来帮助他统计到底有多少个符合条件的密文。

 

【输入数据】

    第一行两个数N,KEY,意义同题目描述;

    第二行N个数表示原文A,意义同题目描述。

 

【输出数据】

    一个数ANS,表示对于原文A和KEY,有多少组可行的密文B。

 

【输入样例】

3 2

1 1 2

 

【输出样例】

2

 

【样例说明】

密文110,1*1+1*1+0*2=2

密文001,0*1+0*1+1*2=2

一共两组可行的密文。

 

【数据约定】

60%数据满足N<=25

100%数据满足N<=40,-maxlongint<=∑▒Ai<=maxlongint

/*    设了long long类型的变量,用“%lld”怎么也读不进去,必须用cin或者qread*/#include
#include
using namespace std;int n;long long a[50],key;long long qread(){ long long i=0; int j=1; char ch=getchar(); while(ch<'0'||ch>'9'){
if(ch=='-')j=-1;ch=getchar();} while(ch<='9'&&ch>='0'){i=i*10+ch-'0';ch=getchar();} return i*j;}long long dfs(int pos,long long sum){ if(pos==n+1){ if(sum==key)return 1; return 0; } long long ans=0; ans+=dfs(pos+1,sum+a[pos]); ans+=dfs(pos+1,sum); return ans;}int main(){ //freopen("Cola.txt","r",stdin); freopen("password.in","r",stdin); freopen("password.out","w",stdout); scanf("%d",&n); key=qread(); for(int i=1;i<=n;i++)a[i]=qread(); cout<
60分 暴力
#include
#include
#include
#include
#include
#include
#include
#include
#define ll long longusing namespace std;inline int read(){ int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){ if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f;}bool flag;ll ans;int n,cnt,key;int a[55];map
b;void dfs(int x,int now){ if(x==cnt+1){ if(!flag)b[now]++; else ans+=b[key-now]; return; } dfs(x+1,now+a[x]); dfs(x+1,now);}int main(){ freopen("password.in","r",stdin); freopen("password.out","w",stdout); n=read();key=read(); for(int i=1;i<=n;i++) a[i]=read(); cnt=n/2;dfs(1,0); flag=1;cnt=n;dfs(n/2+1,0); printf("%I64d",ans); return 0;}
100分 折半搜索

 

2、球的序列(formation.*)

   N个编号为1-n的球,每个球都有唯一的编号。这些球被排成两种序列,分别为A、B序列,现在需要重新寻找一个球的序列l,对于这个子序列l中任意的两个球,要求j,k(j<k),都要求满足lj在A中位置比lk在A中位置靠前,却lj在B中位置比lk在B中位置靠前,请你计算这个子序列l的最大长度。

输入:

第一行一个整数,表示N。

第二行N个整数,表示A序列。

第三行N个整数,表示B序列。

 

样例输入

5

1 2 4 3 5

5 2 3 4 1

 

样例输出

2

样例说明

L可以是{2,3},也可以是{2,4}

 

数据范围:

40% N<=5000

100% N<=50000

O(nlogn)的最长上升子序列

开一个栈,每次取栈顶元素top和读到的元素temp做比较,如果temp > top 则将temp入栈;如果temp < top则二分查找栈中的比temp大的第1个数,并用temp替换它。 最长序列长度即为栈的大小top。

这也是很好理解的,对于x和y,如果x < y且Stack[y] < Stack[x],用Stack[x]替换Stack[y],此时的最长序列长度没有改变但序列Q的''潜力''增大了。
举例:原序列为1,5,8,3,6,7
栈为1,5,8,此时读到3,用3替换5,得到1,3,8; 再读6,用6替换8,得到1,3,6;再读7,得到最终栈为1,3,6,7。最长递增子序列为长度4。
我想,当出现1,5,8,2这种情况时,栈内最后的数是1,2,8不是正确的序列啊?难道错了?
分析一下,我们可以看出,虽然有些时候这样得不到正确的序列了,但最后算出来的个数是没错的,为什么呢?
想想,当temp>top时,总个数直接加1,这肯定没错;但当temp<top时呢? 这时temp肯定只是替换了栈里面的某一个元素,所以大小不变,就是说一个小于栈顶的元素加入时,总个数不变。这两种情况的分析可以看出,如果只求个数的话,这个算法比较高效。但如果要求打印出序列时,就只能用DP了。

#include
#include
using namespace std;#define maxn 50010int n,a[maxn],b[maxn],c[maxn],f[maxn],dp[maxn];int main(){ freopen("Cola.txt","r",stdin); //freopen("formation.in","r",stdin); //freopen("formation.out","w",stdout); scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%d",&a[i]); c[a[i]]=i; } for(int i=1;i<=n;i++){ scanf("%d",&b[i]); f[i]=c[b[i]];dp[i]=1; } int ans=1; for(int i=2;i<=n;i++) for(int j=1;j
f[j]){ dp[i]=max(dp[i],dp[j]+1); ans=max(ans,dp[i]); } cout<
60分 最长上升子序列
#include
#include
using namespace std;#define maxn 50010int n,a[maxn],b[maxn],c[maxn],f[maxn],dp[maxn];int st[maxn],top;int main(){ //freopen("Cola.txt","r",stdin); freopen("formation.in","r",stdin); freopen("formation.out","w",stdout); scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%d",&a[i]); c[a[i]]=i; } for(int i=1;i<=n;i++){ scanf("%d",&b[i]); f[i]=c[b[i]];dp[i]=1; } for(int i=1;i<=n;i++){ if(f[i]>st[top])st[++top]=f[i]; else{ int pos=0; int l=1,r=top; while(l<=r){ int mid=(l+r)>>1; if(st[mid]>=f[i])pos=mid,r=mid-1; else l=mid+1; } st[pos]=f[i]; } } printf("%d",top);}
100分 贪心的最长上升子序列

 

3、大逃亡(escape.*)

给出数字N(1<=N<=10000),X(1<=x<=1000),Y(1<=Y<=1000),代表有N个敌人分布一个X行Y列的矩阵上,矩形的行号从0到X-1,列号从0到Y-1再给出四个数字x1,y1,x2,y2,代表你要从点(x1,y1)移到(x2,y2)。在移动的过程中你当然希望离敌人的距离的最小值最大化,现在请求出这个值最大可以为多少,以及在这个前提下,你最少要走多少步才可以回到目标点。注意这里距离的定义为两点的曼哈顿距离,即某两个点的坐标分为(a,b),(c,d),那么它们的距离为|a-c|+|b-d|。

输入:

第一行给出数字N,X,Y

第二行给出x1,y1,x2,y2

下面将有N行,给出N个敌人所在的坐标

输出:

在一行内输出你离敌人的距离及在这个距离的限制下,你回到目标点最少要移动多少步。

Sample input

2 5 6

0 0 4 0

2 1

2 3

Sample output

2 14

/*    先暴力预处理出每个点离最近的敌人的距离(这个预处理真的特别暴力)    二分答案,在check每个答案的时候顺便记录下这种答案下的最短路,以为check的方法是灌水,所以不费事*/#include
#include
#include
#include
using namespace std;#define maxn 1010int N,n,m,x1,x2,ans1,y1,y2,d[maxn][maxn],ans2,now,len;bool flag,vis[maxn][maxn];//check中要用的 struct node{ int x,y,step;}cur,nxt;int e[4][2]={
{
0,1},{
1,0},{
0,-1},{-1,0}};int abs(int x){ if(x<0)return -x; return x;}bool bfs(int limit){ queue
q; cur.x=x1;cur.y=y1;cur.step=0; q.push(cur); while(!q.empty()){ cur=q.front();q.pop();vis[cur.x][cur.y]=0; for(int i=0;i<4;i++){ int xx=cur.x+e[i][0],yy=cur.y+e[i][1]; if(xx
=0&&yy
=0&&d[xx][yy]>=limit&&!vis[xx][yy]){ nxt.x=xx;nxt.y=yy;nxt.step=cur.step+1; if(xx==x2&&yy==y2){ len=nxt.step; return 1; } q.push(nxt); vis[xx][yy]=1; } } } return 0;}bool check(int x){ flag=0; memset(vis,0,sizeof(vis)); if(bfs(x)){ ans2=len; return 1; } return 0;}int main(){ //freopen("Cola.txt","r",stdin); freopen("escape.in","r",stdin); freopen("escape.out","w",stdout); memset(d,127/3,sizeof(d)); scanf("%d%d%d",&N,&n,&m); scanf("%d%d%d%d",&x1,&y1,&x2,&y2); int x,y; int l=0x7fffffff,r=0; for(int i=1;i<=N;i++){ scanf("%d%d",&x,&y); d[x][y]=0; for(int i=0;i
>1; if(check(now))ans1=now,l=now+1; else r=now-1; } printf("%d %d",ans1,ans2);}
55分 暴力
#include
#include
#include
#include
using namespace std;#define maxn 1010int N,n,m,x1,x2,ans1,y1,y2,d[maxn][maxn],ans2,now,len;bool flag,vis[maxn][maxn];//check中要用的 struct node{ int x,y,step;}cur,nxt;int e[4][2]={
{
0,1},{
1,0},{
0,-1},{-1,0}};int abs(int x){ if(x<0)return -x; return x;}bool bfs(int limit){ queue
q; cur.x=x1;cur.y=y1;cur.step=0; q.push(cur); while(!q.empty()){ cur=q.front();q.pop();vis[cur.x][cur.y]=0; for(int i=0;i<4;i++){ int xx=cur.x+e[i][0],yy=cur.y+e[i][1]; if(xx
=0&&yy
=0&&d[xx][yy]>=limit&&!vis[xx][yy]){ nxt.x=xx;nxt.y=yy;nxt.step=cur.step+1; if(xx==x2&&yy==y2){ len=nxt.step; return 1; } q.push(nxt); vis[xx][yy]=1; } } } return 0;}bool check(int x){ flag=0; memset(vis,0,sizeof(vis)); if(bfs(x)){ ans2=len; return 1; } return 0;}struct Node{ int x,y;};queue
p;int main(){ //freopen("Cola.txt","r",stdin); freopen("escape.in","r",stdin); freopen("escape.out","w",stdout); memset(d,-1,sizeof(d)); scanf("%d%d%d",&N,&n,&m); scanf("%d%d%d%d",&x1,&y1,&x2,&y2); int x,y; int l=0x7fffffff,r=0; for(int i=1;i<=N;i++){ scanf("%d%d",&x,&y); d[x][y]=0; Node w; w.x=x;w.y=y; p.push(w); } while(!p.empty()){ Node c=p.front();p.pop(); for(int i=0;i<4;i++){ int xx=c.x+e[i][0],yy=c.y+e[i][1]; if(xx>=n||xx<0||yy>=m||yy<0||d[xx][yy]!=-1)continue; d[xx][yy]=d[c.x][c.y]+1; Node r; r.x=xx;r.y=yy; p.push(r); } } l=0,r=min(d[x1][y1],d[x2][y2]); while(l<=r){ now=(l+r)>>1; if(check(now))ans1=now,l=now+1; else r=now-1; } printf("%d %d",ans1,ans2);}
60分 改了下预处理
#include
#include
#include
#include
using namespace std;#define maxn 1010int N,n,m,x1,x2,ans1,y1,y2,d[maxn][maxn],ans2,now,len;bool flag,vis[maxn][maxn];//check中要用的 struct node{ int x,y,step;}cur,nxt;int e[4][2]={
{
0,1},{
1,0},{
0,-1},{-1,0}};int abs(int x){ if(x<0)return -x; return x;}bool bfs(int limit){ queue
q; cur.x=x1;cur.y=y1;cur.step=0; vis[x1][y1]=1; q.push(cur); while(!q.empty()){ cur=q.front();q.pop(); for(int i=0;i<4;i++){ int xx=cur.x+e[i][0],yy=cur.y+e[i][1]; if(xx
=0&&yy
=0&&d[xx][yy]>=limit&&!vis[xx][yy]){ nxt.x=xx;nxt.y=yy;nxt.step=cur.step+1; if(xx==x2&&yy==y2){ len=nxt.step; return 1; } q.push(nxt); vis[xx][yy]=1; } } } return 0;}bool check(int x){ flag=0; memset(vis,0,sizeof(vis)); if(bfs(x)){ ans2=len; return 1; } return 0;}struct Node{ int x,y;};queue
p;int main(){ //freopen("Cola.txt","r",stdin); freopen("escape.in","r",stdin); freopen("escape.out","w",stdout); memset(d,-1,sizeof(d)); scanf("%d%d%d",&N,&n,&m); scanf("%d%d%d%d",&x1,&y1,&x2,&y2); int x,y; int l=0x7fffffff,r=0; for(int i=1;i<=N;i++){ scanf("%d%d",&x,&y); d[x][y]=0; Node w; w.x=x;w.y=y; p.push(w); } while(!p.empty()){ Node c=p.front();p.pop(); for(int i=0;i<4;i++){ int xx=c.x+e[i][0],yy=c.y+e[i][1]; if(xx>=n||xx<0||yy>=m||yy<0||d[xx][yy]!=-1)continue; d[xx][yy]=d[c.x][c.y]+1; Node r; r.x=xx;r.y=yy; p.push(r); } } if(x1==x2&&y1==y2){ printf("%d 0",d[x1][y1]); return 0; } l=0,r=min(d[x1][y1],d[x2][y2]); while(l<=r){ now=(l+r)>>1; if(check(now))ans1=now,l=now+1; else r=now-1; } printf("%d %d",ans1,ans2);}
100分 删掉了bfs中出队列时的vis=1

 

转载于:https://www.cnblogs.com/thmyl/p/7426398.html

你可能感兴趣的文章
SwaggerUI+SpringMVC——构建RestFul API的可视化界面
查看>>
springmvc怎么在启动时自己执行一个线程
查看>>
流操作的规律
查看>>
Python基础学习15--异常的分类与处理
查看>>
javascript运算符的优先级
查看>>
React + Redux 入门(一):抛开 React 学 Redux
查看>>
13位时间戳和时间格式化转换,工具类
查看>>
vue router-link子级返回父级页面
查看>>
C# 通知机制 IObserver<T> 和 IObservable<T>
查看>>
Code of Conduct by jsFoundation
查看>>
div 只显示两行超出部分隐藏
查看>>
C#小练习ⅲ
查看>>
电源防反接保护电路
查看>>
arraylist
查看>>
zoj 1649 Rescue (BFS)(转载)
查看>>
2124: 等差子序列 - BZOJ
查看>>
字符串匹配算法综述
查看>>
Linux centosVMware shell 管道符和作业控制、shell变量、环境变量配置文件
查看>>
【设计模式】工厂模式
查看>>
两个表格中数据不用是一一对应关系--来筛选不同数据,或者相同数据
查看>>