• 2014-10-4 NOIP模拟赛


    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[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<<dfs(1,0);
    }
    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=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<int,int> 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<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=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<i;j++)
                if(f[i]>f[j]){
                    dp[i]=max(dp[i],dp[j]+1);
                    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=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<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[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<node>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<n&&xx>=0&&yy<m&&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<n;i++)
                for(int j=0;j<m;j++)
                    d[i][j]=min(d[i][j],abs(i-x)+abs(j-y));
        }
        for(int i=0;i<n;i++)for(int j=0;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)>>1;
            if(check(now))ans1=now,l=now+1;
            else r=now-1;
        }
        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[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<node>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<n&&xx>=0&&yy<m&&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<Node>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<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[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<node>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<n&&xx>=0&&yy<m&&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<Node>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
  • 相关阅读:
    100个高质量Java开发者博客
    javascript的trigger事件
    js正则函数match、exec、test、search、replace、split使用集合
    Openssl verify命令
    Openssl x509命令
    Openssl req命令
    Openssl asn1parse命令
    Openssl ec命令
    Openssl ecparam命令
    Openssl rsa命令
  • 原文地址:https://www.cnblogs.com/thmyl/p/7426398.html
Copyright © 2020-2023  润新知