zoukankan      html  css  js  c++  java
  • “知乎杯”2018 CCF 大学生计算机系统与程序设计竞赛 分组加密器(encryption)

    分组加密器(encryption)

      题解点这里

    #include<map>
    #include<stack>
    #include<vector>
    #include<cstdio>
    #include<iostream>
    #define debug(x) cerr<<#x<<" "<<x<<endl;
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    const int PLEN=64;
    const int SLEN=8;
    struct ptable_type{
        int input_size,output_size;
        int element[PLEN];
        inline void Read(){
            scanf("%d%d",&input_size,&output_size);
            for(int i=0;i<output_size;i++) scanf("%d",element+i);
        }
    };
    struct sbox_type{
        int input_size,output_size;
        int element[1<<SLEN];
        inline void Read(){
            scanf("%d%d",&input_size,&output_size);
            for(int i=0;i<(1<<input_size);i++) scanf("%d",element+i);
        }
    };
    struct lex_type{
        string name;int type;ull value;
        lex_type(string name="",int type=0,ull value=0):name(name),type(type),value(value){}
    };
    struct bs_var_type{
        string name;int len;ull value;
        bs_var_type(string name="",int len=0,ull value=0):name(name),len(len),value(value){}
        vector<bs_var_type*> ch;
    };
    struct expr_type{
        int id,type;ull value;
        vector<int> bs_varp;
        expr_type *expr1,*expr2;
    };
    struct gra_type{
        int type,var,value,jmp;
        vector<int> bs_varp;
        expr_type* expr;
        int st,ed;//lex[st] .. lex[ed]
    };
    int n,m;
    ptable_type ptable[10];
    sbox_type sbox[10];
    
    string code;//store all characters of the code
    int loop_var[26];
    vector<bs_var_type> bs_var;
    vector<lex_type> lex;
    vector<gra_type> gra;
    stack<int> loop_pos;
    vector<expr_type*> expr_ptr;
    void ReadPtable(){
        for(int i=0;i<n;i++) ptable[i].Read();
    }
    void ReadSbox(){
        for(int i=0;i<m;i++) sbox[i].Read();
    }
    void ReadCode(){
        char ch=getchar();
        while(ch!='
    ') ch=getchar();
        for(bool meet_end=false;;){
            code+=ch=getchar();
            if(ch=='D') meet_end=true;
            if(ch=='L') meet_end=false;
            if(ch=='
    '&&meet_end) break;
        }
    }
    int find_bs(string &name){
        for(int i=0,sz=bs_var.size();i<sz;i++) if(bs_var[i].name==name) return i;
        return -1;
    }
    char type5[7]={'=','+','(',')','[',']','
    '};
    string type0[8]={"BEGIN","END","P","S","LOOP","ENDLOOP","SPLIT","MERGE"};
    void lex_ana(){
        string str;lex_type tmp;
        for(int i=0,j,codelen=code.length();i<codelen;str.clear()){
            while(code[i]==','||code[i]==' '||code[i]=='	') i++;
            str+=code[i++];
            if(str[0]>='A'&&str[0]<='Z'){//type 0
                while(i<codelen&&code[i]>='A'&&code[i]<='Z') str+=code[i++];
                for(j=0;j<8;j++) if(str==type0[j]) break;
                tmp.name=str;tmp.type=0;tmp.value=j;
                lex.push_back(tmp);
            }
            else if(str[0]>='a'&&str[0]<='z'){//type 1 or 2
                while(i<codelen&&code[i]>='a'&&code[i]<='z')  str+=code[i++];
                if(str.length()==1){//type 1
                    lex.push_back(lex_type(str,1,str[0]-'a'));
                }
                else{//type 2
                    j=find_bs(str);
                    if(j==-1){
                        j=bs_var.size();
                        bs_var.push_back(bs_var_type(str,0,0));
                    }
                    lex.push_back(lex_type(str,2,j));
                }
            }
            else if(str[0]>='0'&&str[0]<='9'){ //type 3
                while(i<codelen&&code[i]>='0'&&code[i]<='9') str+=code[i++];
                int strl=str.length(); ull x(0);
                for(j=0;j<strl;j++) x=x*10+str[j]-'0';
                lex.push_back(lex_type(str,3,x));
            }
            else if(str[0]=='"'){   //type 4
                while(i<codelen&&code[i]>='0'&&code[i]<='1') str+=code[i++];
    //            str+=code[i++]);
                i++;
                int strl=str.length();ull x=0;
                for(j=1;j<strl;j++) x=(x<<1)|str[j]-'0';
                lex.push_back(lex_type(str,4,x));
            }
            else{    //type 5
                for(j=0;j<7;j++) if(str[0]==type5[j]) break;
                lex.push_back(lex_type(str,5,j));
            }
        }
    }
    void init_bs_var(){
        for(int i=0,tmp;lex[i].name!="BEGIN";i+=5){
            tmp=lex[i].value;
            bs_var[tmp].len=lex[i+2].value;
            bs_var[tmp].value=0;
        }
    }
    void get_bs_var(int l,int r,ull& value,vector<int>& bs_varp){
        value=lex[l].value;
        for(int i=l + 1;i<r;i+=3){
            if(lex[i+1].type==1) bs_varp.push_back((int)(lex[i+1].value)-26);  // 0..25 -> -26..-1
            else bs_varp.push_back(lex[i+1].value); // 0..63
        }
    }
    expr_type* generate_expr(int l,int r){
        expr_type* ptr=new expr_type;
        ptr->id=expr_ptr.size();
        expr_ptr.push_back(ptr);
        ptr->expr1=NULL;ptr->expr2=NULL;ptr->value=0;
        int i=l;
        for(int num=0;i<=r;i++){
            if(lex[i].name=="(") num++;
            if(lex[i].name==")") num--;
            if(lex[i].name=="+"&&num==0) break;
        }
        if(i<=r){
            ptr->type=2;
            ptr->expr1=generate_expr(l,i-1);
            ptr->expr2=generate_expr(i+1,r);
            return ptr;
        }
        if(lex[l].name=="P"||lex[l].name=="S"){
            if(lex[l].name=="P") ptr->type=3;else ptr->type=4;
            if(lex[l+2].type==1) ptr->value=lex[l+2].value-26;
            else if(lex[l+2].type==3) ptr->value=lex[l+2].value;
            ptr->expr1=generate_expr(l+5,r-1);
            return ptr;
        }
        if(lex[l].type==4){
            ptr->type=1;
            ptr->value=lex[l].value;
            return ptr;
        }
        if(lex[l].type==2){
            ptr->type=0;
            get_bs_var(l,r,ptr->value,ptr->bs_varp);
            return ptr;
        }
    }
    void generate_gra(int l,int r){
        gra_type tmp;
        tmp.st=l;tmp.ed=r;
        tmp.var=tmp.value=tmp.jmp=0;
        tmp.expr=NULL;
        if(lex[l].name=="BEGIN"){
            tmp.type=tmp.value=0;
        }
        else if(lex[l].name=="END"){
            tmp.type=0;
            tmp.value=1;
        }
        else if(lex[l].name=="LOOP"){
            tmp.type=2;
            tmp.var=lex[l+1].value;
            tmp.value=lex[l+2].value;
            tmp.jmp=lex[l+3].value;
            loop_pos.push(gra.size());
        }
        else if(lex[l].name=="ENDLOOP"){
            int pos=loop_pos.top();loop_pos.pop();
            tmp.type=3;
            tmp.var=gra[pos].var;
            tmp.value=gra[pos].jmp;
            gra[pos].jmp=0;
            tmp.jmp=pos+1;
        }
        else if(lex[l].name=="SPLIT"){
            tmp.type=4;
            tmp.value=lex[r-2].value;
            ull beta;
            get_bs_var(l+2,r-3,beta,tmp.bs_varp);
            tmp.var=beta;
        }
        else if(lex[l].name=="MERGE"){
            tmp.type=5;
            ull beta;
            get_bs_var(l+2,r-2,beta,tmp.bs_varp);
            tmp.var=beta;
        }
        else if(lex[l].type==2){   //assignment statement
            int i=l;
            while(i<=r&&lex[i].name!="=") i++;
            tmp.type=1;
            ull beta;
            get_bs_var(l,i-1,beta,tmp.bs_varp);
            tmp.var=beta;
            tmp.expr=generate_expr(i+1,r-1);
        }
        gra.push_back(tmp);
    }
    void gra_ana(){
        int i=0,j,sz=lex.size();
        for(i=0;lex[i].name!="BEGIN";i++);
        for(;i<sz;i=j+1){
            for(j=i;lex[j].name!="
    ";j++);
            generate_gra(i,j);
        }
    }
    void bs_to_num(const string& str,ull& num){
        num=0;
        for(int i=0,sz=str.length();i<sz;i++) num=(num<<1)|str[i]-'0';
    }
    void num_to_bs(const ull& num,string& str,int size=PLEN){
        str.clear();
        for(ull tmp=1ull<<size-1;tmp;tmp>>=1) if(num&tmp) str+='1';else str+='0';
    }
    string int_to_str(int i){
        string str;
        stack<char>s;
        if(i==0){str="0";return str;}
        if(i<0) str+='-',i=-i;
        for(;i>0;i/=10) s.push((i%10)+'0');
        while(!s.empty()) str+=s.top(),s.pop();
        return str;
    }
    bs_var_type* find_bs_varp(ll pos,const vector<int>& bs_varp){
        bs_var_type* ptr=&bs_var[pos];//?????
        for(int i=0,sz=bs_varp.size();i<sz;i++){
            int j=bs_varp[i];
            if(j<0) j=loop_var[j+26];
            ptr=ptr->ch[j];
        }
        return ptr;
    }
    ull cal_expr(expr_type* ptr){
        if(ptr->type==0) return find_bs_varp(ptr->value,ptr->bs_varp)->value;
        else if(ptr->type==1) return ptr->value;
        else if(ptr->type==2) return cal_expr(ptr->expr1)^cal_expr(ptr->expr2);
        else if(ptr->type==3){
            ull tmp=cal_expr(ptr->expr1);
            ll j=ptr->value;
            if(j<0) j=loop_var[j+26];
            string sin,sout;
            num_to_bs(tmp,sin,ptable[j].input_size);
            for(int i=0;i<ptable[j].output_size;i++)
                sout.push_back(sin[ptable[j].element[i]]);
            bs_to_num(sout,tmp);
            return tmp;
        }
        else if(ptr->type==4){
            ull tmp=cal_expr(ptr->expr1);
            ll j=ptr->value;
            if(j<0) j=loop_var[j+26];
            return sbox[j].element[tmp];
        }
    }
    ull encrypt(ull state,ull key){
        for(int now=0;;){
            if(gra[now].type==0){
                if(gra[now].value==0){   //BEGIN
                    bs_var[0].value=state;
                    bs_var[1].value=key;
                    for(int i=2;i<bs_var.size();i++) bs_var[i].value=0;
                    now++;
                }
                else return bs_var[0].value;  //END
            }
            else if(gra[now].type==1){
                bs_var_type* ptr=find_bs_varp(gra[now].var,gra[now].bs_varp);
                ptr->value=cal_expr(gra[now].expr);
                now++;
            }
            else if(gra[now].type==2){
                loop_var[gra[now].var]=gra[now].value;
                now++;
            }
            else if(gra[now].type==3){
                loop_var[gra[now].var]++;
                if(loop_var[gra[now].var]>gra[now].value) now++;
                else now=gra[now].jmp;
            }
            else if(gra[now].type==4){
                bs_var_type* ptr=find_bs_varp(gra[now].var,gra[now].bs_varp);
                int tmp=gra[now].value;
                int chlen=ptr->len / tmp;
                for(int i=0;i<tmp;i++){
                    bs_var_type* chptr=new bs_var_type;
                    chptr->len=chlen;
                    chptr->name=ptr->name+"["+int_to_str(i)+"]";
                    chptr->value=0;
                    ptr->ch.push_back(chptr);
                }
                ull beta=(1ull<<chlen)-1;
                for(int i=tmp-1;~i;i--){
                    ptr->ch[i]->value=ptr->value & beta;
                    ptr->value=ptr->value>>chlen;
                }
                now++;
            }
            else if(gra[now].type==5){
                bs_var_type* ptr=find_bs_varp(gra[now].var,gra[now].bs_varp);
                int tmp=ptr->ch.size();
                int chlen=ptr->len / tmp;
                ptr->value=0;
                for(int i=0;i<tmp;i++){
                    bs_var_type* chptr=ptr->ch[i];
                    ptr->value=(ptr->value<<chlen)|chptr->value;
                    delete chptr;
                }
                ptr->ch.clear();
                now++;
            }
        }
    }
    void InitTaskA(){
        scanf("%d%d",&n,&m);
        ReadPtable();
        ReadSbox();
        ReadCode();
    }
    void SolveTaskA(){
        lex_ana();
        init_bs_var();
        gra_ana();
        int k; ull state,key; string str1,str2;
        scanf("%d",&k);
        for(int i=0;i<k;i++){
            cin>>str1>>str2;
            bs_to_num(str1,state);
            bs_to_num(str2,key);
            num_to_bs(encrypt(state,key),str1,bs_var[0].len);
            puts(str1.c_str());
        }
    }
    void taskB_init(){
        code="state(32)
    ";
        code += "key(12)
    ";
        code += "dkey(16)
    ";
        code += "tmp(32)
    ";
        code += "BEGIN
    ";
        code += "SPLIT(dkey,4)
    ";
        code += "SPLIT(key,3)
    ";
        code += "dkey[0]=key[0]
    ";
        code += "dkey[1]=key[1]
    ";
        code += "dkey[2]=key[2]
    ";
        code += "dkey[3]=key[0] + key[1] + key[2]
    ";
        code += "MERGE(key)
    ";
        code += "MERGE(dkey)
    ";
        code += "LOOP i 1 16
    ";
        code += "dkey=P[2](dkey)
    ";
        code += "tmp=state
    ";
        code += "SPLIT(state,2)
    ";
        code += "SPLIT(tmp,2)
    ";
        code += "state[0]=tmp[1]
    ";
        code += "tmp[1]=tmp[1] + dkey
    ";
        code += "SPLIT(tmp[1],4)
    ";
        code += "LOOP j 0 3
    ";
        code += "tmp[1][j]=S[0](tmp[1][j])
    ";
        code += "ENDLOOP
    ";
        code += "MERGE(tmp[1])
    ";
        code += "state[1]=tmp[0] + P[0](tmp[1])
    ";
        code += "MERGE(state)
    ";
        code += "MERGE(tmp)
    ";
        code += "dkey=P[1](dkey)
    ";
        code += "ENDLOOP
    ";
        code += "tmp=state
    ";
        code += "SPLIT(state,2)
    ";
        code += "SPLIT(tmp,2)
    ";
        code += "state[0]=tmp[1]
    ";
        code += "state[1]=tmp[0]
    ";
        code += "MERGE(state)
    ";
        code += "MERGE(tmp)
    ";
        code += "END
    ";
        n=3;
        m=1;
        ptable[0].input_size=16;
        ptable[0].output_size=16;
        ptable[1].input_size=16;
        ptable[1].output_size=16;
        ptable[2].input_size=16;
        ptable[2].output_size=16;
        sbox[0].input_size=4;
        sbox[0].output_size=4;
        int p0[16]={12, 1, 9, 2, 0, 11, 7, 3, 4, 15, 8, 5, 14, 13, 10, 6};
        int p1[16]={1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0};
        int p2[16]={0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
        int s0[16]={12, 5, 6, 11, 9, 0, 10, 13, 3, 14, 15, 8, 4, 7, 1, 2};
        for(int i=0;i<16;i++){
            ptable[0].element[i]=p0[i];
            ptable[1].element[i]=p1[i];
            ptable[2].element[i]=p2[i];
            sbox[0].element[i]=s0[i];
        }
    }
    void solve_taskB(){
        lex_ana();
        init_bs_var();
        gra_ana();
        ull state, ans, tmp;
        string str1, str2;
        int key1,key2;
        map<ull,int> h;
        cin >> str1 >> str2;
        bs_to_num(str1,state);
        bs_to_num(str2,ans);
        for(int i=0;i<4096;i++){
            tmp=encrypt(state,i);
            h[tmp]=i;
        }
        int p1[16]={0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
        int p2[16]={15, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14};
        for(int i=0;i<16;i++){
            ptable[1].element[i]=p1[i];
            ptable[2].element[i]=p2[i];
        }
        for(int i=0;i<4096;i++){
            tmp=encrypt(ans,i);
            if(h.find(tmp)==h.end()) continue;
            key1=h[tmp];
            key2=i;
            num_to_bs(key1,str1,12);
            num_to_bs(key2,str2,12);
            cout << "YES" << endl;
            cout << str1 << endl;
            cout << str2 << endl;
            return;
        }
        cout << "NO" << endl;
    }
    char task_id[10];
    int main(){
        freopen("encryption.in","r",stdin);
        freopen("encryption.out","w",stdout);
        scanf("%s",task_id);
        if(task_id[4]=='A'){
            InitTaskA();
            SolveTaskA();
        } 
        else{
    //        puts("NO");//pass 3 points
            taskB_init();
            solve_taskB();
        }
        fclose(stdin);fclose(stdout);
        return 0;
    }
  • 相关阅读:
    Java数据结构与算法之---求两个数的最大公约数(欧几里得算法)
    Linux下面配置文件~/.bash_profile
    Java数据结构之回溯算法的递归应用迷宫的路径问题
    Java数据结构之对称矩阵的压缩算法---
    Java数据结构之字符串模式匹配算法---KMP算法2
    Java数据结构之字符串模式匹配算法---KMP算法
    Java数据结构之字符串模式匹配算法---Brute-Force算法
    Java数据结构之表的增删对比---ArrayList与LinkedList之一
    Java数据结构之队列的实现以及队列的应用之----简单生产者消费者应用
    Java堆栈的应用1----------堆栈的自定义实现以及括号匹配算法的Java实现
  • 原文地址:https://www.cnblogs.com/shenben/p/11614874.html
Copyright © 2011-2022 走看看