【kAriOJ】离散数学春季学期编程测试 1
A。凱撒密碼
題意:
給你k1,k2,和一串明文,一串密文。
明文用k1加密,密文用k2解密。
對(duì)于明文要把字母轉(zhuǎn)換成大寫字母,非字母全部刪除。
額:要考慮到取模可能會(huì)變成負(fù)數(shù),所以要加一下26再取模。
代碼:
#include<stdio.h> #define N 85 int k1, k2; char plain[N], cipher[N]; void init(char s[]) //預(yù)處理,轉(zhuǎn)換為大寫字母 {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)加密明文。將明文字母轉(zhuǎn)換成數(shù)字,按8位數(shù)字分段,不足部分補(bǔ)足0。明文中有非字母刪除,A和a轉(zhuǎn)成數(shù)字都是00, Z和z轉(zhuǎn)成數(shù)字都是25。明文數(shù)字8位分段的每一段對(duì)應(yīng)的密文也要求是8位,如果不足8位,前面補(bǔ)足0。
對(duì)于明文要把字母轉(zhuǎn)換成大寫字母,非字母全部刪除。
補(bǔ)充:
RSA加密就是字母轉(zhuǎn)化為兩位數(shù)字,分段處理,比如每八個(gè)一段,M為明文數(shù)字段,C為密文數(shù)字段,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[]) //預(yù)處理,轉(zhuǎn)換為大寫字母 {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') ; //明文對(duì)應(yīng)的數(shù)字串k++;if(k == 4) //夠8位數(shù)字時(shí) {printf("%08lld", qpow(block, e) % 100000000);//輸出密文,這個(gè)模不知道是不是必須的,題目沒說n的上限block = 0;k = 0;}}if(k)//剩下的明文要后面補(bǔ)零 {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)加密明文。將明文字母轉(zhuǎn)換成數(shù)字,按8位數(shù)字分段,不足部分補(bǔ)足0。明文中有非字母刪除,A和a轉(zhuǎn)成數(shù)字都是00, Z和z轉(zhuǎn)成數(shù)字都是25。明文數(shù)字8位分段的每一段對(duì)應(yīng)的密文也要求是8位,如果不足8位,前面補(bǔ)足0。
對(duì)于明文要把字母轉(zhuǎn)換成大寫字母,非字母全部刪除。
補(bǔ)充:
RSA加密就是字母轉(zhuǎn)化為兩位數(shù)字,分段處理,比如每八個(gè)一段,M為明文數(shù)字段,C為密文數(shù)字段,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)//擴(kuò)展歐幾里德求逆元 {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)//密文達(dá)到8位數(shù)字時(shí) {memset(plain, 0, sizeof plain);//清空明文字符串block = qpow(block, d);//計(jì)算明文數(shù)字串for(j = 3; j >= 0; j--)//每次計(jì)算兩位數(shù)字并存在明文字符串中,因?yàn)閺暮竺嫱叭?#xff0c;所以倒過來存 {plain[j] = block % 100 + 'A';//取最后面兩個(gè)數(shù)字block /= 100;//去掉最后面兩個(gè)數(shù)字 }printf("%s", plain);//輸出明文k = 0;//清空計(jì)數(shù)器 }} } int main() {// freopen("in.txt", "r", stdin);scanf("%lld%lld ", &n, &e);gets(cipher);init();printf("%d\n", d);decrypt();return 0; }?
總結(jié)
以上是生活随笔為你收集整理的【kAriOJ】离散数学春季学期编程测试 1的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 数据、事实、实体、值对象、事务、不变性
- 下一篇: 技术网站 --入门无忧网