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<iostream>
#include<cstdio>
using namespace std;
int n;
long long a[],key;
long long qread(){
long long i=;
int j=;
char ch=getchar();
while(ch<''||ch>''){if(ch=='-')j=-;ch=getchar();}
while(ch<=''&&ch>=''){i=i*+ch-'';ch=getchar();}
return i*j;
}
long long dfs(int pos,long long sum){
if(pos==n+){
if(sum==key)return ;
return ;
}
long long ans=;
ans+=dfs(pos+,sum+a[pos]);
ans+=dfs(pos+,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=;i<=n;i++)a[i]=qread();
cout<<dfs(,);
}

60分 暴力

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<map>
#include<vector>
#define ll long long
using namespace std;
inline int read()
{
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
bool flag;
ll ans;
int n,cnt,key;
int a[];
map<int,int> b;
void dfs(int x,int now){
if(x==cnt+){
if(!flag)b[now]++;
else ans+=b[key-now];
return;
}
dfs(x+,now+a[x]);
dfs(x+,now);
}
int main(){
freopen("password.in","r",stdin);
freopen("password.out","w",stdout);
n=read();key=read();
for(int i=;i<=n;i++)
a[i]=read();
cnt=n/;dfs(,);
flag=;cnt=n;dfs(n/+,);
printf("%I64d",ans);
return ;
}

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<iostream>
#include<cstdio>
using namespace std;
#define maxn 50010
int 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=;i<=n;i++){
scanf("%d",&a[i]);
c[a[i]]=i;
}
for(int i=;i<=n;i++){
scanf("%d",&b[i]);
f[i]=c[b[i]];dp[i]=;
}
int ans=;
for(int i=;i<=n;i++)
for(int j=;j<i;j++)
if(f[i]>f[j]){
dp[i]=max(dp[i],dp[j]+);
ans=max(ans,dp[i]);
}
cout<<ans;
}

60分 最长上升子序列

#include<iostream>
#include<cstdio>
using namespace std;
#define maxn 50010
int 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=;i<=n;i++){
scanf("%d",&a[i]);
c[a[i]]=i;
}
for(int i=;i<=n;i++){
scanf("%d",&b[i]);
f[i]=c[b[i]];dp[i]=;
}
for(int i=;i<=n;i++){
if(f[i]>st[top])st[++top]=f[i];
else{
int pos=;
int l=,r=top;
while(l<=r){
int mid=(l+r)>>;
if(st[mid]>=f[i])pos=mid,r=mid-;
else l=mid+;
}
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<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
#define maxn 1010
int 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[][]={{,},{,},{,-},{-,}};
int abs(int x){
if(x<)return -x;
return x;
}
bool bfs(int limit){
queue<node>q;
cur.x=x1;cur.y=y1;cur.step=;
q.push(cur);
while(!q.empty()){
cur=q.front();q.pop();vis[cur.x][cur.y]=;
for(int i=;i<;i++){
int xx=cur.x+e[i][],yy=cur.y+e[i][];
if(xx<n&&xx>=&&yy<m&&yy>=&&d[xx][yy]>=limit&&!vis[xx][yy]){
nxt.x=xx;nxt.y=yy;nxt.step=cur.step+;
if(xx==x2&&yy==y2){
len=nxt.step;
return ;
}
q.push(nxt);
vis[xx][yy]=;
}
}
}
return ;
}
bool check(int x){
flag=;
memset(vis,,sizeof(vis));
if(bfs(x)){
ans2=len;
return ;
}
return ;
}
int main(){
//freopen("Cola.txt","r",stdin);
freopen("escape.in","r",stdin);
freopen("escape.out","w",stdout);
memset(d,/,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=;
for(int i=;i<=N;i++){
scanf("%d%d",&x,&y);
d[x][y]=;
for(int i=;i<n;i++)
for(int j=;j<m;j++)
d[i][j]=min(d[i][j],abs(i-x)+abs(j-y));
}
for(int i=;i<n;i++)for(int j=;j<m;j++)r=max(r,d[i][j]),l=min(l,d[i][j]);
r=min(r,min(d[x1][y1],d[x2][y2]));
while(l<=r){
now=(l+r)>>;
if(check(now))ans1=now,l=now+;
else r=now-;
}
printf("%d %d",ans1,ans2);
}

55分 暴力

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
#define maxn 1010
int 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[][]={{,},{,},{,-},{-,}};
int abs(int x){
if(x<)return -x;
return x;
}
bool bfs(int limit){
queue<node>q;
cur.x=x1;cur.y=y1;cur.step=;
q.push(cur);
while(!q.empty()){
cur=q.front();q.pop();vis[cur.x][cur.y]=;
for(int i=;i<;i++){
int xx=cur.x+e[i][],yy=cur.y+e[i][];
if(xx<n&&xx>=&&yy<m&&yy>=&&d[xx][yy]>=limit&&!vis[xx][yy]){
nxt.x=xx;nxt.y=yy;nxt.step=cur.step+;
if(xx==x2&&yy==y2){
len=nxt.step;
return ;
}
q.push(nxt);
vis[xx][yy]=;
}
}
}
return ;
}
bool check(int x){
flag=;
memset(vis,,sizeof(vis));
if(bfs(x)){
ans2=len;
return ;
}
return ;
}
struct Node{
int x,y;
};
queue<Node>p;
int main(){
//freopen("Cola.txt","r",stdin);
freopen("escape.in","r",stdin);
freopen("escape.out","w",stdout);
memset(d,-,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=;
for(int i=;i<=N;i++){
scanf("%d%d",&x,&y);
d[x][y]=;
Node w;
w.x=x;w.y=y;
p.push(w);
}
while(!p.empty()){
Node c=p.front();p.pop();
for(int i=;i<;i++){
int xx=c.x+e[i][],yy=c.y+e[i][];
if(xx>=n||xx<||yy>=m||yy<||d[xx][yy]!=-)continue;
d[xx][yy]=d[c.x][c.y]+;
Node r;
r.x=xx;r.y=yy;
p.push(r);
}
}
l=,r=min(d[x1][y1],d[x2][y2]);
while(l<=r){
now=(l+r)>>;
if(check(now))ans1=now,l=now+;
else r=now-;
}
printf("%d %d",ans1,ans2);
}

60分 改了下预处理

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
#define maxn 1010
int 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[][]={{,},{,},{,-},{-,}};
int abs(int x){
if(x<)return -x;
return x;
}
bool bfs(int limit){
queue<node>q;
cur.x=x1;cur.y=y1;cur.step=;
vis[x1][y1]=;
q.push(cur);
while(!q.empty()){
cur=q.front();q.pop();
for(int i=;i<;i++){
int xx=cur.x+e[i][],yy=cur.y+e[i][];
if(xx<n&&xx>=&&yy<m&&yy>=&&d[xx][yy]>=limit&&!vis[xx][yy]){
nxt.x=xx;nxt.y=yy;nxt.step=cur.step+;
if(xx==x2&&yy==y2){
len=nxt.step;
return ;
}
q.push(nxt);
vis[xx][yy]=;
}
}
}
return ;
}
bool check(int x){
flag=;
memset(vis,,sizeof(vis));
if(bfs(x)){
ans2=len;
return ;
}
return ;
}
struct Node{
int x,y;
};
queue<Node>p;
int main(){
//freopen("Cola.txt","r",stdin);
freopen("escape.in","r",stdin);
freopen("escape.out","w",stdout);
memset(d,-,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=;
for(int i=;i<=N;i++){
scanf("%d%d",&x,&y);
d[x][y]=;
Node w;
w.x=x;w.y=y;
p.push(w);
}
while(!p.empty()){
Node c=p.front();p.pop();
for(int i=;i<;i++){
int xx=c.x+e[i][],yy=c.y+e[i][];
if(xx>=n||xx<||yy>=m||yy<||d[xx][yy]!=-)continue;
d[xx][yy]=d[c.x][c.y]+;
Node r;
r.x=xx;r.y=yy;
p.push(r);
}
}
if(x1==x2&&y1==y2){
printf("%d 0",d[x1][y1]);
return ;
}
l=,r=min(d[x1][y1],d[x2][y2]);
while(l<=r){
now=(l+r)>>;
if(check(now))ans1=now,l=now+;
else r=now-;
}
printf("%d %d",ans1,ans2);
}

100分 删掉了bfs中出队列时的vis=1

2014-10-4 NOIP模拟赛的更多相关文章

  1. 10.17 NOIP模拟赛

    目录 2018.10.17 NOIP模拟赛 A 咒语curse B 神光light(二分 DP) C 迷宫maze(次短路) 考试代码 B 2018.10.17 NOIP模拟赛 时间:1h15min( ...

  2. 10.16 NOIP模拟赛

    目录 2018.10.16 NOIP模拟赛 A 购物shop B 期望exp(DP 期望 按位计算) C 魔法迷宫maze(状压 暴力) 考试代码 C 2018.10.16 NOIP模拟赛 时间:2h ...

  3. 2018.10.16 NOIP模拟赛解题报告

    心路历程 预计得分:\(100 + 100 + 20 = 220\) 实际得分:\(100 + 100 + 30 = 230\) 辣鸡模拟赛.. T1T2都是一眼题,T3考验卡常数还只有一档暴力分. ...

  4. 2016.10.30 NOIP模拟赛 day2 PM 整理

    满分:300分 直接全部爆零,真的是很坑啊! 10.30的题目+数据:链接:http://pan.baidu.com/s/1jHXLace 密码:i784 T1: 题目中的难点就是每次折叠的点可能应经 ...

  5. 2016.10.30 NOIP模拟赛 day2 AM 整理

    题目+数据:链接:http://pan.baidu.com/s/1gfBg4h1 密码:ho7o 总共得了:130分, 1:100分  2:30分(只会这30分的暴力) 3:0(毫无思路) 虽然不高, ...

  6. 2017 10.25 NOIP模拟赛

    期望得分:100+40+100=240 实际得分:50+40+20=110 T1 start取了min没有用,w(゚Д゚)w    O(≧口≦)O T3 代码3个bug :数组开小了,一个细节没注意, ...

  7. 2018.10.03 NOIP+ 模拟赛 解题报告

    得分: \(30+5+0=35\)(考得真不咋滴) \(T1\):奥义商店(点此看题面) 以为很简单,对着这题想了一个多小时,最后果断打了个暴力交了... ... 看完题解发现其实也不是很难. 对于\ ...

  8. 2018.10.30 NOIp模拟赛 T1 改造二叉树

    [题目描述] 小Y在学树论时看到了有关二叉树的介绍:在计算机科学中,二叉树是每个结点最多有两个子结点的有序树.通常子结点被称作“左孩子”和“右孩子”.二叉树被用作二叉搜索树和二叉堆.随后他又和他人讨论 ...

  9. 2016.10.29 NOIP模拟赛 PM 考试整理

    300分的题,只得了第三题的100分. 题目+数据:链接:http://pan.baidu.com/s/1o7P4YXs 密码:4how T1:这道题目存在着诸多的问题: 1.开始的序列是无法消除的( ...

  10. 2018.10.30 NOIp模拟赛T2 数字对

    [题目描述] 小 H 是个善于思考的学生,现在她又在思考一个有关序列的问题.        她的面前浮现出一个长度为 n 的序列{ai},她想找出一段区间[L, R](1 <= L <= ...

随机推荐

  1. 转载 j2ee j2se j2me 区别,mvc 和ssh联系理解

    [转]J2SE J2EE J2ME的区别 以及 MVC与SSH对应关系 2014-3-6阅读322 评论0 J2SE J2EE J2ME的区别多数编程语言都有预选编译好的类库以支持各种特定的功能,在J ...

  2. PAT 甲级 1028. List Sorting (25) 【结构体排序】

    题目链接 https://www.patest.cn/contests/pat-a-practise/1028 思路 就按照 它的三种方式 设计 comp 函数 然后快排就好了 但是 如果用 c++ ...

  3. deepin 安装微信与QQ

    安装QQ sudo apt-get install deepin.com.qq.im 安装微信 sudo apt-get install deepin.com.wechat 附录 其他安装包 http ...

  4. Cocos2d-x中定时器的使用

    CCTimer:轻量级的计时器 CCTimer (void) ccTime  getInterval (void) void  setInterval (ccTime fInterval) bool  ...

  5. rand()与srand()

    1.不用srand()的话 两次运行程序产生的随机数序列相同 2.用srand() 两次运行程序产生的随机数则不同 示例程序: #include<iostream> #include< ...

  6. blog集合

    godiscoder的技术blog 一个不错的技术架构设计blog MySQLOPS 数据库与运维自动化技术分享 stone的技术blog 陈皓专栏 风雪涟漪的技术blog 华为首席科学家 张宴技术b ...

  7. 网络编程学习笔记-MAC地址和IP地址的关系

    简单地说:ip地址是服务商给你的,mac地址是你的网卡物理地址. 一.IP地址 对于IP地址,相信大家都很熟悉,即指使用TCP/IP协议指定给主机的32位地址.IP地址由用点分隔开的4个8八位组构成, ...

  8. Codeforces Gym 101190 NEERC 16 .L List of Primes(递归)

    ls特别喜欢素数,他总是喜欢把素数集合的所有子集写下来,并按照一定的顺序和格式.对于每一个子集,集合内 的元素在写下来时是按照升序排序的,对于若干个集合,则以集合元素之和作为第一关键字,集合的字典序作 ...

  9. java-04 数组和二维数组

    java 中内存分配地址值以及栈和堆得区别: ##########数组操作的两个常见小问题(越界和空指针)############## 数组索引越界异常,访问了不存在的索引: 空指针: ####### ...

  10. BZOJ1855 [Scoi2010]股票交易[单调队列dp]

    题 题面有点复杂,不概括了. 后面的状态有前面的最优解获得大致方向是dp.先是瞎想了个$f[i][j]$表示第$i$天手里有$j$张股票时最大收入(当天无所谓买不买). 然后写了一个$O(n^4)$状 ...