zoukankan      html  css  js  c++  java
  • UVA306 Cipher[循环节]

    UVA306 CipherUVA306 Cipher


    Descriptionmathcal{Description}

    Bob和Alice开始使用一种全新的编码方案。令人惊讶的是,这不是公共关键字密码系统,他们的编码和解码都是基于一种特殊的密码。他们于1996年2月16日在费城的最后一次会议上确定了他们的密码。他们把密码定为一个含有n个不同整数的数列,a1,…,an(0<ai<=n)。解码根据以下原则:把信息写在密钥的下方,使信息中的字符和密钥中的数字相应对齐。在位置i处的消息字符被写入位置ai处,其中ai是密钥中相应的编号。得到的消息以相同的方式继续被编码。重复这个过程k次,第k个编码即是最后答案。

    消息的长度总是小于或等于n。若消息长度小于n,用空格补齐。

    请你帮助Alice和Bob编写一个读取密钥的程序,进行k次编码,产生编码消息。

    N&lt;=10,000N&lt;=10,000


    Solutionmathcal{Solution}

    最初想法
    求出整个置换的循环节长度, 对于后面的每个询问, 都模循环节后暴力进行模拟.
    时间复杂度 O(N)O(循环节大小*N),
    LuoguLuoguACcolor{green}{AC},
    V JudgeV JudgeTLEcolor{blue}{TLE}.


    正解部分
    由于 整个置换 的循环节大小为 所有 子循环节 大小的 LCMLCM,
    导致时间复杂度为 O(LCMN)O(LCM*N), 其中 LCMLCM 的上限为 N!N!, 在luogu竟然还能A.

    但若求出每个位置单个的循环节, 对每个询问就可以 O(sizeN)O(size*N) 得到答案, sizesize 的上限为 NN.

    求出整个置换的循环节大小需要 2500ms2500ms 左右,
    但是求出单个循环节大小仅需要 20ms20ms.


    实现部分
    没什么好说的.


    Codemathcal{Code}

    #include<cstdio>
    #include<cstring>
    #define reg register
    
    const int maxn = 205;
    
    int N;
    int K;
    int A[maxn];
    int B[maxn];
    int l[maxn];
    
    char S[maxn];
    char Ans[maxn];
    
    void Work(){
            getchar();
            scanf("%[^
    ]", S+1);
            int len = strlen(S+1);
            while(len < N) S[++ len] = ' ';
            for(reg int i = 1; i <= N; i ++) B[i] = i;
            for(reg int i = 1; i <= N; i ++){
                    int tmp = K % l[i];
                    while(tmp --) B[i] = A[B[i]];
            }
            for(reg int i = 1; i <= N; i ++) Ans[B[i]] = S[i];
            for(reg int i = 1; i <= N; i ++) printf("%c", Ans[i]);
            printf("
    ");
    }
    
    int main(){
            while(~scanf("%d", &N) && N){
                    for(reg int i = 1; i <= N; i ++) scanf("%d", &A[i]);
                    for(reg int i = 1; i<= N; i ++){
                            int t = i, to = A[i]; l[i] = 1;
                            while(to != t) l[i] ++, to = A[to];
                    }
                    while(~scanf("%d", &K) && K) Work();
                    printf("
    ");
            }
            return 0;
    }
    
    
    
  • 相关阅读:
    【PAT甲级】1014 Waiting in Line (30 分)(队列维护)
    【PAT甲级】1013 Battle Over Cities (25 分)(并查集,简单联通图)
    获取当前时间
    设备版本,设备号,APP版本,APP名称获取
    获取设备号
    Button的图像位置设置
    UIButton设置imgae图片自适应button的大小且不变形
    手势图片:拖拽捏合旋转放大
    Unable to add App ID because the '10' App ID limit in '7' days has been exceeded.
    iOS开发系列--触摸事件、手势识别、摇晃事件、耳机线控
  • 原文地址:https://www.cnblogs.com/zbr162/p/11822583.html
Copyright © 2011-2022 走看看