【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 = ; 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 = ; s[i]; i++)
if(s[i] >= 'A' && s[i] <= 'Z')
printf("%c", ((s[i] - 'A' + k*f + ) % + 'A'));
printf("\n");
}
int main()
{
scanf("%d,%d ", &k1, &k2);
gets(plain);
gets(cipher);
encrypt(plain,k1,);
encrypt(cipher,k2,-);
return ;
}

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

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 << ], plain[];
ll exgcd(ll a, ll b)//扩展欧几里德求逆元
{
if(b == )
{
x = ;
y = ;
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 = ;
while(b)
{
if(b & )
ans = (ans * k ) % n;
k = ( k * k) % n;
b >>= ;
}
return ans;
}
void init()//求p和q,和d
{
int i;
for(i = ; i < n; i++)
if(n % i == )
{
p = i;
q = n / i;
break;
}
ll M;
M = (p - ) * (q - );
exgcd(e, M);
d = (x % M + M) % M;//求e的逆元d
}
void decrypt() //解密
{
ll block = ;
int k = , i, j;
for(i = ; cipher[i]; i++)
{
block = block * + cipher[i] - '';//密文从字符串中取出来
k++;
if(k == )//密文达到8位数字时
{
memset(plain, , sizeof plain);//清空明文字符串
block = qpow(block, d);//计算明文数字串
for(j = ; j >= ; j--)//每次计算两位数字并存在明文字符串中,因为从后面往前取,所以倒过来存
{
plain[j] = block % + 'A';//取最后面两个数字
block /= ;//去掉最后面两个数字
}
printf("%s", plain);//输出明文
k = ;//清空计数器
}
}
}
int main()
{
// freopen("in.txt", "r", stdin);
scanf("%lld%lld ", &n, &e);
gets(cipher);
init();
printf("%d\n", d);
decrypt();
return ;
}
上一篇:验分享:CSS浮动(float,clear)通俗讲解


下一篇:c语言的基本语法