希尔加密算法(湖南师范大学第六届大学生计算机程序设计竞赛)hnuoj11552
解密 |
Time Limit: 1000ms, Special Time Limit:2500ms, Memory Limit:65536KB |
Total submit users: 2, Accepted users: 0 |
Problem 11552 : No special judgement |
Problem description |
password学中。有一种加密方法。叫做希尔加密法。 其加密过程例如以下: |
Input |
第一行为一个整数T (0 < T < 20), 表示数据的组数. |
Output |
对每组数据,输出一行,为密文所相应的原文 |
Sample Input |
2 delw 2 11 8 3 7 pabqlzqii 3 1 14 2 5 9 2 4 7 3 |
Sample Output |
july qvtusjkcm |
Problem Source |
HUNNU Contest |
希尔解密。须要先求逆矩阵。
我仅仅能过第一组。
。。
。
大神们,求解释。。。
#include <math.h>
#include <string.h>
#include <malloc.h>
#include <iostream>
#include <iomanip>
#include<stdio.h>
using namespace std;
#define N 105 //定义方阵的最大阶数为10
//函数的声明部分
double MatDet(double *p, int n); //求矩阵的行列式
double Creat_M(double *p, int m, int n, int k); //求矩阵元素A(m, n)的代数余之式
void print(double *p, int n); //输出矩阵n*n
bool Gauss(double A[][N], double B[][N], int n); //採用部分主元的高斯消去法求方阵A的逆矩阵B
double a[N][N],b[N][N];
int c[N][N];
double determ; //定义矩阵的行列式
//int zimu[26];
int gcd(int a,int b)
{
if(!b) return a;
gcd(b,a%b);
}
void Print(int mm[],int k)
{
/*
for(int i=0; i<k; i++)
{
printf("%d ",mm[i]);
}
printf("\n");*/
for(int i=0; i<k; i++)
{
for(int j=0; j<k; j++)
{
printf("%d ",c[i][j]);
}
printf("\n");
}
// double tp[105]= {0};
int tp[105]={0};
for(int i=0; i<k; i++) //列
{
for(int j=0; j<k; j++) //行||mm的行
{
tp[i]+=mm[j]*c[j][i];
// printf("tp=%d\tmm=%d\tb=%d\n",tp[i],mm[j],c[j][i]);
}
}
for(int i=0; i<k; i++)
{
// int tmp=(int)(tp[i]);
// printf("%d\t",tmp);
printf("%c",((tp[i])%26+26)%26+'a');
// while(tp[i]<0) tp[i]+=26;
// printf("%c\n",(int)(tp[i])%26+'a');
}
// printf("\n");
}
int main()
{
// freopen("xier.txt","r",stdin);
double *buffer, *p; //定义数组首地址指针变量
int row, num; //定义矩阵的行数和矩阵元素个数
// int i, j; int n;
// for(int i=0;i<26;i++)
// zimu[i]=i;
int T,len,M,mo[105];
char mi[10005];
scanf("%d",&T);
while(T--)
{
scanf("%s",mi);
len=strlen(mi);
scanf("%d",&n);
row=n;
num = 2*row*row;
buffer = (double *)calloc(num, sizeof(double)); //分配内存单元
p = buffer;
for(int i=0; i<n; i++)
{
for(int j=0; j<n; j++)
{
scanf("%lf",&a[i][j]);
*p++=a[i][j];
}
}
determ = MatDet(buffer, row); //求整个矩阵的行列式
// printf("determ=%lf\n",determ);
int d=gcd((int)(determ),27);
d=(int)determ*27/d;
// printf("***************************************d=%d\n",d);
for (int i = 0; i < row; i++) //求逆矩阵
{
for (int j = 0; j < row; j++)
{
*(p+j*row+i) = Creat_M(buffer, i, j, row)*d/determ;
}
}
print(p, row);
free(buffer); //释放内存空间
for(int i=0; i<len; i++)
{
// printf("mi=%c\n",mi[i]);
mo[i%n]=mi[i]-'a';
// printf("i=%d\tmo=%d\n",i%n,mo[i%n]);
if((i+1)%n==0) Print(mo,n);
}
printf("\n"); // for(int i=0; i<n; i++)
// {
// for(int j=0; j<n; j++)
// {
// printf("%lf ",a[i][j]);
// }
// printf("\n");
// }
// if(Gauss(a,b,n))
// {
/*
for (int i = 0; i < n; i++)
{
cout << setw(4);
for (int j = 0; j < n; j++)
{
cout << b[i][j] << setw(10);
}
cout << endl;
}*/ // }
}
return 0;
}
//-----------------------------------------------
//功能: 求矩阵(n*n)的行列式
//入口參数: 矩阵的首地址,矩阵的行数
//返回值: 矩阵的行列式值
//----------------------------------------------
double MatDet(double *p, int n)
{
int r, c, m;
int lop = 0;
double result = 0;
double mid = 1;
if (n != 1)
{
lop = (n == 2) ? 1 : n; //控制求和循环次数,若为2阶,则循环1次。否则为n次
for (m = 0; m < lop; m++)
{
mid = 1; //顺序求和, 主对角线元素相乘之和
for (r = 0, c = m; r < n; r++, c++)
{
mid = mid * (*(p+r*n+c%n));
}
result += mid;
}
for (m = 0; m < lop; m++)
{
mid = 1; //逆序相减, 减去次对角线元素乘积
for (r = 0, c = n-1-m+n; r < n; r++, c--)
{
mid = mid * (*(p+r*n+c%n));
}
result -= mid;
}
}
else
result = *p;
return result;
}
//----------------------------------------------------------------------------
//功能: 求k*k矩阵中元素A(m, n)的代数余之式
//入口參数: k*k矩阵的首地址。矩阵元素A的下标m,n,矩阵行数k
//返回值: k*k矩阵中元素A(m, n)的代数余之式
//----------------------------------------------------------------------------
double Creat_M(double *p, int m, int n, int k)
{
int len;
int i, j;
double mid_result = 0;
int sign = 1;
double *p_creat, *p_mid;
len = (k-1)*(k-1); //k阶矩阵的代数余之式为k-1阶矩阵
p_creat = (double*)calloc(len, sizeof(double)); //分配内存单元
p_mid = p_creat;
for (i = 0; i < k; i++)
{
for (j = 0; j < k; j++)
{
if (i != m && j != n) //将除第i行和第j列外的全部元素存储到以p_mid为首地址的内存单元
{
*p_mid++ = *(p+i*k+j);
}
}
}
sign = (m+n)%2 == 0 ? 1 : -1; //代数余之式前面的正、负号
mid_result = (double)sign*MatDet(p_creat, k-1);
free(p_creat);
return mid_result;
}
//-----------------------------------------------------
//功能: 打印n*n矩阵
//入口參数: n*n矩阵的首地址,矩阵的行数n
//返回值: 无返回值
//-----------------------------------------------------
void print(double *p, int n)
{
int i, j;
for (i = 0; i < n; i++)
{
// cout << setw(4);
for (j = 0; j < n; j++)
{
c[i][j]=(int)*p++;
while(c[i][j]<0) c[i][j]+=26;
// cout << setiosflags(ios::right) << *p++ << setw(10);
}
// cout << endl;
}
}
//------------------------------------------------------------------
//功能: 採用部分主元的高斯消去法求方阵A的逆矩阵B
//入口參数: 输入方阵,输出方阵,方阵阶数
//返回值: true or false
//-------------------------------------------------------------------
bool Gauss(double A[][N], double B[][N], int n)
{
int i, j, k;
double max, temp;
double t[N][N]; //暂时矩阵
//将A矩阵存放在暂时矩阵t[n][n]中
for (i = 0; i < n; i++)
{
for (j = 0; j < n; j++)
{
t[i][j] = A[i][j];
}
}
//初始化B矩阵为单位阵
for (i = 0; i < n; i++)
{
for (j = 0; j < n; j++)
{
B[i][j] = (i == j) ? (double)1 : 0;
}
}
for (i = 0; i < n; i++)
{
//寻找主元
max = t[i][i];
k = i;
for (j = i+1; j < n; j++)
{
if (fabs(t[j][i]) > fabs(max))
{
max = t[j][i];
k = j;
}
}
//假设主元所在行不是第i行,进行行交换
if (k != i)
{
for (j = 0; j < n; j++)
{
temp = t[i][j];
t[i][j] = t[k][j];
t[k][j] = temp;
//B伴随交换
temp = B[i][j];
B[i][j] = B[k][j];
B[k][j] = temp;
}
}
//推断主元是否为0, 若是, 则矩阵A不是满秩矩阵,不存在逆矩阵
if (t[i][i] == 0)
{
cout << "There is no inverse matrix!";
return false;
}
//消去A的第i列除去i行以外的各行元素
temp = t[i][i];
for (j = 0; j < n; j++)
{
t[i][j] = t[i][j] / temp; //主对角线上的元素变为1
B[i][j] = B[i][j] / temp; //伴随计算
}
for (j = 0; j < n; j++) //第0行->第n行
{
if (j != i) //不是第i行
{
temp = t[j][i];
for (k = 0; k < n; k++) //第j行元素 - i行元素*j列i行元素
{
t[j][k] = t[j][k] - t[i][k]*temp;
B[j][k] = B[j][k] - B[i][k]*temp;
}
}
}
}
for(int i=0; i<n; i++)
{
for(int j=0; j<n; j++)
{
B[i][j]*=determ;
}
//printf("\n");
}
return true;
}
希尔加密算法(湖南师范大学第六届大学生计算机程序设计竞赛)hnuoj11552的更多相关文章
- 湖南省第十三届大学生计算机程序设计竞赛 Football Training Camp 贪心
2007: Football Training Camp[原创-转载请说明] Submit Page Summary Time Limit: 1 Sec Memory Limit: 1 ...
- 浙江省第十六届大学生ACM程序设计竞赛部分题解
E .Sequence in the Pocket sol:将数组copy一份,然后sort一下,找寻后面最多多少个元素在原数组中保持有序,用总个数减去已经有序的就是我们需要移动的次数. 思维题 #i ...
- CSUOJ1329——一行盒子_湖南省第九届大学生计算机程序设计竞赛
题目是中文的我就不是说明了,比赛的时候看过题目后队友说是splay来做,细想来省赛不会出这么坑的题目吧. 于是比赛还有一个小时左右把该做的都做完了以后,我们队三个人都来思考这个题目了.不过还好很快我们 ...
- 2018湖南省第14届大学生计算机程序设计竞赛 D: 卖萌表情
Description 已知以下 4 种都是卖萌表情(空白的部分可以是任意字符.竖线是便于展示的分隔符,没有实际意义): ^ ^ | ^ | < | > v | v v | > | ...
- 2018湖南省第14届大学生计算机程序设计竞赛 C: 时间旅行
Description 假设 Bobo 位于时间轴(数轴)上 t0 点,他要使用时间机器回到区间 (0, h] 中. 当 Bobo 位于时间轴上 t 点,同时时间机器有 c 单位燃料时,他可以选择一个 ...
- 2018湖南省第14届大学生计算机程序设计竞赛 A字符画
Description 读入 w,请输出 2018 的字符画,两个数字之间有 w 个空格.具体格式请参考样例输出. 1 ≤ w ≤ 2018 Input 输入文件只包含 1 个整数 w. Output ...
- 湖南省第九届大学生计算机程序设计竞赛 Interesting Calculator
Interesting Calculator Time Limit: 2 Sec Memory Limit: 128 MB Submit: 163 Solved: 49 Description T ...
- csu 1503: 点弧之间的距离-湖南省第十届大学生计算机程序设计大赛
这是--比量p并用交点连接中心不上弧.在于:它至p距离.是不是p与端点之间的最短距离 #include<iostream> #include<map> #include< ...
- 华东师范大学第十届ECNU Coder程序设计竞赛
华东师范大学第十届ECNU Coder程序设计竞赛 浮点数模运算 solution 转成整数然后取模. 时间复杂度:\(O(1)\) 数螃蟹 solution 找出公差出现次数最多的作为公差,然后找出 ...
随机推荐
- JDBC基础01
今日知识 1. JDBC基本概念2. 快速入门3. 对JDBC中各个接口和类详解 JDBC: 1. 概念:Java DataBase Connectivity Java 数据库连接, Java语言操作 ...
- Nginx 配置埋点js日志采集
页面埋点&nginx日志采集 页面(web容器:httpd/nginx负载均衡 + apache server)<===> 日志采集服务器(nginx服务器) 通过某个页面跳转到我 ...
- Python3没有dict.has_key方法
最近开始学习Python,安装上最新的Python3.3.3照书敲了一个小程序结果报错 'dict' object has no attribute 'has_key' 上网查也找不到解决办法,后来发 ...
- C - Puzzles
Problem description The end of the school year is near and Ms. Manana, the teacher, will soon have t ...
- lua math.random()
math.random([n [,m]]) 用法:1.无参调用,产生[0, 1)之间的浮点随机数. 2.一个参数n,产生[1, n]之间的整数. 3.两个参数,产生[n, m]之间的整数. math. ...
- Android 解决toolbar标题不显示问题
问题原因:toolbar的兼容性有问题 解决办法: setSupportActionBar(toolbar); toolbar使用步骤: 1.编写menu.xml 为了保持兼容需要这样写: andro ...
- 查询 MySQL 库/表相关信息
SHOW DATABASES //列出 MySQL Server 数据库. SHOW TABLES [FROM db_name] //列出数据库数据表. SHOW CREATE TABLES tbl_ ...
- NagiosQL安装
NagiosQL和Nconf是比较好用的Nagios配置工具. 一.安装NagiosQL 1.在服务器终端运行以下命令: ##YUM安装PHP模块yum -y install --disabl ...
- C# treeView 控件
#region --基础 ////设置目录树 ////添加根节点 //treeView1.Nodes.Add("0000000"); ////添加子节点 ////treeView1 ...
- concurrently - npm 同时运行前端和后台服务
项目基于vue(前端)+node(后台),需要启动两个服务 0.文件夹结构及package.json内容: 1.客户端 npm run dev 2.服务器 cd server npm run serv ...