• 10.26 noip模拟试题


    enc
    【问题背景】
    zhx 和他的妹子聊天。
    【问题描述】
    考虑一种简单的加密算法。
    假定所有句子都由小写英文字母构成,对于每一个字母,我们将它唯一地映
    射到另一个字母。例如考虑映射规则:
    a->b, b->c, c->d, d->a. 那么单词 bad 就会被映射为 cba。这个映射规则的“逆
    映射规则”为: b->a, c->b, d->c, a->d。 对于密文 cba, 我们很容易将它解密为 bad。
    当然,这样的映射需要保证每一个字母映射到的字母是不同的(即不可以出
    现两个不同的字母映射到同一个字母,否则将会无法解密) 。
    一种常见的密码攻击方式被称为已知明文攻击。具体地,在你不知道映射表
    的情况下,给你一段明文和对应的密文,你可以推导出一些的映射规则,下一次
    你收到一条密文,你就可能可以解密它。现在你需要完成这样的一个系统。
    【输入格式】
    第一行包含一个字符串,仅包含小写字母,表示一段明文。
    第二行包含一个字符串,仅包含小写字母,表示这段明文对应的密文,保证
    两行长度相同。
    第三行包含一个字符串,仅包含小写字母,表示你需要解密的密文。
    【输出格式】
    输出共一行,表示输入中第三行密文对应的明文。如果不能解密,输出
    “ERROR”(不包含引号) 。注意输入可能出现不自恰的情况。
    【样例输入】
    ab
    cc
    cc
    【样例输出】
    ERROR
    【样例输入】
    ab
    ab
    c
    【样例输出】
    ERROR
    【样例输入】
    abcde
    bcdea
    cad
    【样例输出】
    bec
    【数据范围与规定】
    对于100%的数据,所有字符串长度<=1000。

    /*模拟 有特殊情况没想到 如果25个都已经对应好了 剩下的即使不出现也能对应了 90*/
    #include<cstdio>
    #include<cstring>
    #define maxn 1010
    using namespace std;
    int n,len,f[210],g[210],falg,c1,c2,A,B;
    char s[maxn],s1[maxn],s2[maxn];
    int main()
    {
        freopen("enc.in","r",stdin);
        freopen("enc.out","w",stdout);
        scanf("%s%s%s",s1,s2,s);
        n=strlen(s1);len=strlen(s);
        for(int i=0;i<n;i++){
            if(g[s1[i]]&&g[s1[i]]!=s2[i]){
                falg=1;break;
            }
            if(f[s2[i]]&&f[s2[i]]!=s1[i]){
                falg=1;break;
            }
            if(f[s2[i]]==0)f[s2[i]]=s1[i],c1++;
            if(g[s1[i]]==0)g[s1[i]]=s2[i],c2++;
        }
        if(c1==25&&c2==25){
            for(int i='a';i<='z';i++)
                if(f[i]==0)A=i;
            for(int i='a';i<='z';i++)
                if(g[i]==0)B=i;
            f[A]=B;
        }
        for(int i=0;i<len;i++)
            if(f[s[i]]==0){
                falg=1;break;
            }
        
        if(falg){
            printf("ERROR
    ");return 0;
        }
        for(int i=0;i<len;i++)
            printf("%c",f[s[i]]);
        return 0;
    }
    View Code


    【问题背景】
    zhx 给他的妹子们排序。
    【问题描述】
    zhx 有 N 个妹子,他对第 i 个妹子的好感度为? ? , 且所有? ? ,两两不相等。现
    在 N 个妹子随意站成一排,他要将她们根据好感度从小到大排序。他使用的是
    冒泡排序算法(详见下) 。如果排序过程中好感度为? ? 的妹子和好感度为? ? 的妹
    子发生了交换,那么她们之间会发生一场口角。
    现在 zhx 想知道,给定妹子的初始排列,在排序完成后,最多存在多少个妹
    子,她们任意两人之间没发生过口角。
    正式地,考虑对数组? ? 进行冒泡排序,如果? ? 和? ? 在排序过程中发生交换,
    那么在两个元素之间连一条边。 你需要求出, 排序结束后, 最多存在多少个元素,
    其中任意两个元素之间不存在连边。冒牌排序算法如下:
    【输入格式】
    第一行两个整数 N,表示妹子数量。
    接下来一行 N 个整数? ? ,表示初始第 i 个妹子的好感度。
    【输出格式】
    一行一个整数,表示最多满足要求的妹子的个数。
    【样例输入】
    3
    3 1 2
    【样例输出】
    2
    【样例解释】
    {1, 2}。
    【数据规模与约定】
    316。
    70%的数据,1 ≤ ? ≤ 50。
    对于100%的数据,1 ≤ ? ≤ 100000, 0 ≤ ? ? < ?。

    /*手打个冒泡 把swap的输出出来不难发现就是求LIS*/
    #include<cstdio>
    #include<algorithm>
    #define maxn 100010
    using namespace std;
    int n,x,c[maxn],num;
    int init(){
        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 main()
    {
        freopen("sort.in","r",stdin);
        freopen("sort.out","w",stdout);
        n=init();c[0]=-0x7fffffff;
        for(int i=1;i<=n;i++){
            x=init();
            if(x>c[num]){
                c[++num]=x;continue;
            }
            int pos=lower_bound(c+1,c+1+num,x)-c;
            c[pos]=x;
        }
        printf("%d
    ",num);
        return 0;
    }
    View Code


    【问题背景】
    zhx 和他的妹子(们)做游戏。
    【问题描述】
    考虑 N 个人玩一个游戏, 任意两个人之间进行一场游戏 (共 N*(N-1)/2 场) ,
    且每场一定能分出胜负。
    现在,你需要在其中找到三个人构成“剪刀石头步”局面:三个人 A,B,C
    满足 A 战胜 B,B 战胜 C,C 战胜 A。
    【输入格式】
    第一行一个正整数 N,表示参加游戏的人数。
    接下来 N 行,每行 N 个数 0/1,中间没有空格隔开。第 i 行第 j 列数字为 1
    表示 i 在游戏中战胜了 j。所有对角线元素(即第 i 行第 i 个元素)为 0,保证数
    据合法。
    【输出格式】
    如果存在三个人构成“剪刀石头布”局面,输出三个人的编号(从 1 开始) 。
    如果不存在这样的三个人,输出一个数-1。
    【样例输入】
    5
    00100
    10000
    01001
    11101
    11000
    【样例输出】
    1 3 2
    【数据规模与约定】
    55。
    80%的数据,1 ≤ ? ≤ 10。
    对于100%的数据,1 ≤ ? ≤ 5000

    /*暴力枚举三个点是谁 应该可以80 */
    #include<cstdio>
    #include<ctime>
    #define maxn 5010
    using namespace std;
    int n,num,head[maxn],ans[maxn][2],f[maxn],falg;
    struct node{
        int v,pre;
    }e[maxn*maxn];
    char s[maxn][maxn];
    void Add(int from,int to){
        num++;e[num].v=to;
        e[num].pre=head[from];
        head[from]=num;
    }
    int main()
    {
        freopen("game.in","r",stdin);
        freopen("game.out","w",stdout);
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%s",s[i]+1);
            for(int j=1;j<=n;j++)
                if(s[i][j]=='1')Add(i,j);
        }
        for(int x=1;x<=n;x++){
            for(int i=head[x];i;i=e[i].pre){
                int y=e[i].v;
                for(int j=head[y];j;j=e[j].pre){
                    int z=e[j].v;
                    if(s[z][x]=='1'){
                        if(f[x]==0){
                            f[x]=1;ans[x][0]=y;ans[x][1]=z;
                        }
                        else if(ans[x][0]>y){
                            ans[x][0]=y;ans[x][1]=z;
                        }
                        else if(ans[x][0]==y&&ans[x][1]>z)
                            ans[x][1]=z;
                    }
                }
            }
            if(f[x]){
                printf("%d %d %d
    ",x,ans[x][0],ans[x][1]);
                falg=1;break;
            }
        }
        if(!falg)printf("-1
    ");
        return 0;
    }
    View Code
    /*
    这题真是够了 题目没说清楚
    special judge 还没发用
    自己打了80分的 应该是没啥问题
    然而超时
    虽然到最后改成了20 2333
    但是自己测试的答案是没问题的
    有个spj就好了
    说说正解的思想吧
    很巧妙地降低了复杂度
    首先找环 找到的第一个>=3的环
    (其实不会存在2的)
    就停下 答案一定在这里面的三个
    为什么呢
    首先要是环大小为3 这没啥问题
    关键是>3的 为什么一定存在合法的 合法的怎么找
    这就有套路了
    可以自己画个环 因为保证每两人之间都有边
    那么无论怎么加边 一定会构成一个三元环
    自己动手画画吧 应该很容易看出来 (就是想不到23333)
    照这样的的话 那一定有两个是挨着的 
    但如果枚举两个的话就很慢了 
    我们只枚举一个 并且把一个固定在起点
    我们把起点作为x 枚举的这个作为y 他后面的这个作为z
    那么 y->z 一定有边 然后我们加判断 保证 z->x有边
    现在就剩下一条了就是x->y的这条 如果这条也确定的话 就构成环了
    我们放慢这个枚举的过程来看的话
    第一次 x=1 y=2 z=3 这时可以保证 x->y 有边
    如果z->x 有边的话 就找到了 停下 
    如果没有z->x的边 根据两两必有输赢的题意
    那一定是x->z 有边 
    然后我们到下一层 那就保证了x->y 有边了
    后面一样的 这里画图脑补一下吧 
    这样就好了 
    */
    #include<cstdio>
    #include<stack>
    #include<vector>
    #define maxn 5010
    using namespace std;
    int n,num,head[maxn],dfn[maxn],low[maxn],f[maxn],falg,top,topt,sum,c[maxn];
    stack<int>S;
    vector<int>G[maxn];
    struct node{
        int v,pre;
    }e[maxn*maxn];
    char s[maxn][maxn];
    void Add(int from,int to){
        num++;e[num].v=to;
        e[num].pre=head[from];
        head[from]=num;
    }
    void Tarjan(int u){
        dfn[u]=low[u]=++topt;
        f[u]=1;S.push(u);
        for(int i=head[u];i;i=e[i].pre){
            int v=e[i].v;
            if(dfn[v]==0){
                Tarjan(v);
                low[u]=min(low[u],low[v]);
            }
            else if(f[v])low[u]=min(low[u],dfn[v]);
        }
        if(low[u]==dfn[u]){
            while(u!=S.top()){
                c[++c[0]]=S.top();f[S.top()]=0;S.pop();
            }
            c[++c[0]]=S.top();f[S.top()]=0;S.pop();
            if(c[0]<3)c[0]=0;
            else {
                sum++;falg=1;
                for(int i=c[0];i>=1;i--)
                    G[sum].push_back(c[i]);
            }
        }
    }
    void Printf(){
        for(int k=1;k<=sum;k++)
            if(G[k].size()>=3){
            int x,y,z;x=G[k][0];
            for(int i=0;i<G[k].size()-1;i++){
                y=G[k][i];z=G[k][i+1];
                if(s[z][x]=='1'){
                    printf("%d %d %d
    ",x,y,z);break;
                }
            }
            break;
        }
    }
    int main()
    {
        freopen("game.in","r",stdin);
        freopen("game.ans","w",stdout);
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%s",s[i]+1);
            for(int j=1;j<=n;j++)
                if(s[i][j]=='1')Add(i,j);
        }
        for(int i=1;i<=n;i++){
            if(dfn[i]==0)Tarjan(i);
            if(falg){
                Printf();break;
            }
        }
        if(!falg)printf("-1
    ");
        return 0;
    }
    View Code
  • 相关阅读:
    Linux中/etc目录下passwd和shadow文件
    Linux基本命令
    Linux目录结构说明与基本操作
    如何用虚拟机VMware Workstation安装CentOs-7
    VPP源码分析及流程图
    VPP环境搭建及配置
    【转】智能指针的交叉引用问题及解决方法
    二叉树的前 中 后 层序遍历
    排序算法
    C和C++的一些区别
  • 原文地址:https://www.cnblogs.com/yanlifneg/p/6000877.html
Copyright © 2020-2023  润新知