摘要:
计算Pn(x) = an * x^n + an-1 * x^(n-1) + ... + a1 * x + a0直接计算,需要做的乘法次数 1+2+3+……+n = n(1+n)/2 = O(n2)使用Horner规则,Pn(x) = ((... ((anx + an-1)x + an-2)x + ... + a2)x + a1)x + a0需要做的乘法次数 n = O(n)public class Horner{ public static int compute(int x, int[] A){ //计算Pn(x) = an * x^n + an-1 * x^(n-1) ... 阅读全文
摘要:
利用GF(2^8)乘法逆元,以及矩阵运算,可以构造出AES的SBOX。求乘法逆元的一般方法是利用扩展欧几里得定理,在这里我取了个巧。因为我已经有了GF的指数表(见上一篇文),利用指数表可以轻易地构造出乘法逆元表。具体方法如下:若 x = 3^m, y = 3^n, x 与 y 互为乘法逆元,则有x * y = 3^m * 3^n = 1 = 3^255(任意乘法逆元的255次方必定为1,有点类似费尔马小定理),则m+n=255#include#include#include using namespace std;unsigned char exp[256], log[256], inv[25 阅读全文
摘要:
利用指数表和对数表,实现GF(2^8)的乘法优化。首先利用简单的基础的GF(2^8)乘法,构造指数表和对数表。在这里选取生成元3。指数表exp[i] = 3^i,对数表log[i] = log3(i)。要实现x 与 y 相乘,首先利用对数表找出3^m = x, 3^n = y,这时的乘法就是 x * y = 3^m * 3^n = 3^(m+n),然后利用指数表找到exp[m+n]对应的值。因此所有的乘法都变成了查表操作,提高了效率。但是对于数域较大时,保存对数表和指数表的空间要求较高。典型的牺牲空间换取时间。#include#includeusing namespace std;unsign 阅读全文
摘要:
目的是找出所有GF(2^8)的生成元。方法很简单,从2开始遍历,将每个元素都与自身相乘255次,看是否能得到1~255。若能,则是生成元。#include#includeusing namespace std;unsigned char GFmul(unsigned char a, unsigned char b){ //GF(2^8) 乘法 unsigned char result = 0; if((b&1) == 1)result = a; b >>= 1; for(int i = 1; i 127){ a = (a >= 1; ... 阅读全文
摘要:
最近在学AES,实现了一下伽罗瓦域(2^8)乘法。至于什么是伽罗瓦域解释起来比较复杂,我也不一定能解释清楚,自行google。这里只是给出一个简单直观的实现。#include#includeusing namespace std;unsigned char GFmul(unsigned char a, unsigned char b){ //GF(2^8) 乘法 unsigned char result = 0; //若b为奇数,则先累积a if((b&1) == 1)result = a; b >>= 1; for(int i = 1; i 127){ ... 阅读全文
摘要:
插入排序的一个不错改进。与梳排序类似,希尔排序也用到gap的概念。基本思路是:将原先的一行元素以gap为分界分成几段排成几行,然后按列来用插入排序。不断缩小gap直至1.代码中用到的一个小优化是维基上看到的,据说此比率效率较高,由Knuth提出。另外,还有一个优化基于下面的观察。按照常规思路来说,对于每一个gap,我们应该分别对每一列来做插入排序。但是很显然,不同列之间是不会相互干扰的,因此,在代码中直接从第一列第二个元素开始递增,不断做插入排序。相邻的元素位于不同的列,因此它们并不会影响到彼此,对于同一列的元素,在这一列两个元素之间做了其他什么运算并没影响。这样写代码更加简洁。public 阅读全文
摘要:
冒泡排序的一个不错的改进。与希尔排序有点类似,梳排序在冒泡排序的基础上,提出了gap的概念,使元素的推进快了很多。相当于将原先的一行元素以gap为分界分成几段排成几行,然后按列来用冒泡排序。然后不断缩小gap直至gap为1或元素已经有序(这是冒泡排序的一个特点,凡是改编自冒泡排序(如鸡尾酒排序)都有这个特点,即在遍历过程中就可以确认已经排好序)。public static void combSort(int[] A){ int gap = A.length; boolean unsorted = true; while(gap > 1 || unsorted){ ... 阅读全文
摘要:
Bogo的变种,继续卖萌。。。Bogo每次都随机打乱数组,而Bozo每次随机选择两个位置,然后交换这两个位置的值。相同的是不断靠概率不断查看有序了没。。。public static void bozoSort(int[] A){ Random rand = new Random(); while(!inOrder(A)){ int i = rand.nextInt(A.length); int j = rand.nextInt(A.length); swap(A, i, j); }}Java 阅读全文
摘要:
我不知道这个能不能算排序。。。维基上有这个排序名称。。。但我感觉它纯碎在卖萌。。。基本思路:随机打乱数组,然后看看数组有序了没,如果没?继续随机打乱继续看。。。直至有序。神一般的低效。排几十个数不知道要跑多久。。。public static void bogoSort(int[] A){ while(!inOrder(A)) shuffle(A);}private static boolean inOrder(int[] A){ for(int i = 0; i A[i+1])return false; } return true;}private st... 阅读全文
摘要:
又叫臭皮匠排序。。。在《算法导论》作为反例出现的漂亮但极其低效的排序算法。基本思路是:只要数组长度大于3,先将头与尾排序,然后递归调用排序前三分之二,再递归调用排序后三分之二,最后再递归调用排序前三分之二。冗余计算不少啊。。其实简单来说就是在三个数排序的基础上拓展出来的,相当低效。private static void stoogeSortDo(int[] A, int low, int high){ if(A[low] > A[high]) swap(A, low, high); if(high-low+1 >= 3){ int split = (hi... 阅读全文