【kAriOJ】离散数学春季学期编程测试 1
生活随笔
收集整理的这篇文章主要介绍了
【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("\n"); } 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\n", d);decrypt();return 0; }
总结
以上是生活随笔为你收集整理的【kAriOJ】离散数学春季学期编程测试 1的全部内容,希望文章能够帮你解决所遇到的问题。
- 上一篇: 数据、事实、实体、值对象、事务、不变性
- 下一篇: 技术网站 --入门无忧网