zoukankan      html  css  js  c++  java
  • 【kAriOJ】离散数学春季学期编程测试 1

    A。凯撒密码

    题意:

    给你k1,k2,和一串明文,一串密文。

    明文用k1加密,密文用k2解密。

    对于明文要把字母转换成大写字母,非字母全部删除。

    额:要考虑到取模可能会变成负数,所以要加一下26再取模。

    代码:

    #include<stdio.h>
    #define N 85
    int k1, k2;
    char plain[N], cipher[N];
    void init(char s[]) //预处理,转换为大写字母
    {
        int i;
        for(i = 0; s[i]; i++)
            if(s[i] >= 'a' && s[i] <= 'z')
                s[i] = s[i] - 'a' + 'A';
    }
    void encrypt(char s[],int k,int f)//加解密
    {
        init(s);
        int i;
        for(i = 0; s[i]; i++)
            if(s[i] >= 'A' && s[i] <= 'Z')
                printf("%c", ((s[i] - 'A' + k*f + 26) % 26  + 'A'));
        printf("
    ");
    }
    int main()
    {
        scanf("%d,%d ", &k1, &k2);
        gets(plain);
        gets(cipher);
        encrypt(plain,k1,1);
        encrypt(cipher,k2,-1);
        return 0;
    }

    B。RSA加密 

    题意:

    给你n,e,和一串明文。用(n,e)加密明文。将明文字母转换成数字,按8位数字分段,不足部分补足0明文中有非字母删除,A和a转成数字都是00, Z和z转成数字都是25。明文数字8位分段的每一段对应的密文也要求是8位,如果不足8位,前面补足0。

    对于明文要把字母转换成大写字母,非字母全部删除。

    补充:

    RSA加密就是字母转化为两位数字,分段处理,比如每八个一段,M为明文数字段,C为密文数字段,C=Me%n。

    代码:

    #include<stdio.h>
    #include<string.h>
    #define N 1000
    #define ll long long
    ll n, e;
    char plain[N];
    ll qpow(ll a, ll b)//快速幂
    {
        ll k = a % n;
        ll ans = 1;
        while(b)
        {
            if(b & 1)
                ans = (ans * k ) % n;
            k = ( k * k) % n;
            b >>= 1;
        }
        return ans;
    }
    void init(char s[]) //预处理,转换为大写字母
    {
        int i;
        for(i = 0; s[i]; i++)
            if(s[i] >= 'a' && s[i] <= 'z')
                s[i] = s[i] - 'a' + 'A';
    }
    void encrypt(char s[]) //加密
    {
        init(s);
        int k = 0,i;
        ll block = 0;
        for(i = 0; s[i]; i++)
            if(s[i] >= 'A' && s[i] <= 'Z') //如果是字母
            {
                block = block * 100 + (s[i] - 'A') ; //明文对应的数字串
                k++;
                if(k == 4) //够8位数字时
                {
                    printf("%08lld", qpow(block, e) % 100000000);//输出密文,这个模不知道是不是必须的,题目没说n的上限
                    block = 0;
                    k = 0;
                }
            }
        if(k)//剩下的明文要后面补零
        {
            while(k != 4)
            {
                block = block * 100;
                k++;
            }
            printf("%08lld", qpow(block, e) % 100000000);
        }
    }
    int main()
    {
        //  freopen("in.txt", "r", stdin);
        scanf("%lld%lld ", &n, &e);
        gets(plain);
        encrypt(plain);
        return 0;
    }

    C。RSA解密 

    题意:

    给你n,e,和一串明文。用(n,e)加密明文。将明文字母转换成数字,按8位数字分段,不足部分补足0。明文中有非字母删除,A和a转成数字都是00, Z和z转成数字都是25。明文数字8位分段的每一段对应的密文也要求是8位,如果不足8位,前面补足0。

    对于明文要把字母转换成大写字母,非字母全部删除。

    补充:

    RSA加密就是字母转化为两位数字,分段处理,比如每八个一段,M为明文数字段,C为密文数字段,C=Me%n。

    代码:

    #include<stdio.h>
    #include<string.h>
    #define N 802
    #define ll long long
    ll n, e, p, q, d, x, y;
    char cipher[N << 1], plain[10];
    ll exgcd(ll a, ll b)//扩展欧几里德求逆元
    {
        if(b == 0)
        {
            x = 1;
            y = 0;
            return a;
        }
        ll r = exgcd(b, a % b);
        ll tmp = x;
        x = y;
        y = tmp - a / b * y;
        return r;
    }
    ll qpow(ll a, ll b)//快速幂
    {
        ll k = a % n;
        ll ans = 1;
        while(b)
        {
            if(b & 1)
                ans = (ans * k ) % n;
            k = ( k * k) % n;
            b >>= 1;
        }
        return ans;
    }
    void init()//求p和q,和d
    {
        int i;
        for(i = 2; i < n; i++)
            if(n % i == 0)
            {
                p = i;
                q = n / i;
                break;
            }
        ll M;
        M = (p - 1) * (q - 1);
        exgcd(e, M);
        d = (x % M + M) % M;//求e的逆元d
    }
    void decrypt() //解密
    {
        ll block = 0;
        int k = 0, i, j;
        for(i = 0; cipher[i]; i++)
        {
            block = block * 10 + cipher[i] - '0';//密文从字符串中取出来
            k++;
            if(k == 8)//密文达到8位数字时
            {
                memset(plain, 0, sizeof plain);//清空明文字符串
                block = qpow(block, d);//计算明文数字串
                for(j = 3; j >= 0; j--)//每次计算两位数字并存在明文字符串中,因为从后面往前取,所以倒过来存
                {
                    plain[j] = block % 100 + 'A';//取最后面两个数字
                    block /= 100;//去掉最后面两个数字
                }
                printf("%s", plain);//输出明文
                k = 0;//清空计数器
            }
        }
    }
    int main()
    {
        //  freopen("in.txt", "r", stdin);
        scanf("%lld%lld ", &n, &e);
        gets(cipher);
        init();
        printf("%d
    ", d);
        decrypt();
        return 0;
    }
  • 相关阅读:
    【7】用Laravel5.1开发一个简单的博客系统
    【6】Laravel5.1的migration数据库迁移
    【5】说说Laravel5的blade模板
    【4】优化一下【3】的例子,顺便说说细节
    【3】创建一个简单的Laravel例子
    【2】最简单的Laravel5.1程序分析
    【1】Laravel5.1 安装
    【0】Laravel 5.1 简介
    MySQL常用命令
    Windows8.1使用博客客户端写博客
  • 原文地址:https://www.cnblogs.com/flipped/p/5538145.html
Copyright © 2011-2022 走看看