10 2013 档案

摘要:与快速幂类似.http://www.cnblogs.com/7hat/p/3387267.html只是在每次运算的时候要作mod m运算,利用的是模运算规则 (a * b) mod m = ((a mod m) * (b mod m)) mod m.因为python直接支持大整数运算,所以这次用python来做,检验结果的对错。从另外一个角度上看,用快速幂取模的方法比直接求幂再取模的方法要快,因为将乘数限制在一定的范围。"""e = e0*(2^0) + e1*(2^1) + e2*(2^2) + ... + en * (2^n)b^e = b^(e0*(2^0) 阅读全文
posted @ 2013-10-31 08:10 7hat 阅读(3903) 评论(0) 推荐(0)
摘要:Description:Decode the message.You intercept the following message, which you know has been encoded using the modulusm = 956331992007843552652604425031376690367 and exponent e = 12398737.Break the code and decipher the message.821566670681253393182493050080875560504,870741731290463997209497869585113 阅读全文
posted @ 2013-10-30 07:13 7hat 阅读(980) 评论(0) 推荐(0)
摘要:之前写过SBOX的构造,后来看到别人的优秀思路,借鉴过来重新改了一点。原文地址:http://www.cnblogs.com/7hat/p/3383546.html主要是将矩阵运算改为列运算之和,提高了效率。#include#include#include using namespace std;unsigned char exp[256], log[256], inv[256];unsigned char GFmul(unsigned char a, unsigned char b){ //GF(2^8) 乘法 unsigned char result = 0; if((b... 阅读全文
posted @ 2013-10-29 21:00 7hat 阅读(612) 评论(0) 推荐(0)
摘要:分治的经典算法。import java.util.Random;import java.util.Arrays;public class BinarySearch{ public static int binarySearch(int[] A, int x){ return binarySearchDo(A, x, 0, A.length-1); } private static int binarySearchDo(int[] A, int x, int low, int high){ if(low > high) retu... 阅读全文
posted @ 2013-10-29 08:50 7hat 阅读(214) 评论(0) 推荐(0)
摘要:同时找出一个序列中的最小值最大值,一般方法需要2*(n-1)的比较次数。运用分治,可以降低比较次数。基本思路:把序列分为两部分,找出前半部分的最小值与最大值,再找出后半部分的最小值与最大值,然后比较得出整个序列的最小值与最大值。一直划分到序列只有两个元素时,则直接比较两个元素并返回结果。比较次数分析:f(1) = 1; f(2) = 1; 当n为奇数时,f(n) = f([n/2]) + f(n-[n/2]) + 2; 当n为偶数时,f(n) = 2*f(n/2) + 2.可以证明比较次数最多不超过3*[n/2]。import java.util.Random;import java.util 阅读全文
posted @ 2013-10-28 19:17 7hat 阅读(395) 评论(0) 推荐(0)
摘要:给定一个n,返回1, 2, 3, ... , n 的全排列。这里给出两种方法。它们的时间复杂度都是O(n!),因为n的全排列有n!种。1.基于以下观察:第k个位置可以是1, 2, 3, ... , or n。如,第一个位置可以是1, 2, 3, ... , or n,在确定这个位置的数后,那么第二个位置的数就可以是除已确定的数之外的数,如此类推,知道确定到第n-1个位置上的数(此时第n个位置的数显然也确定了)。例如,n=3, 全排列(和代码输出的可能略有差异,但思路是这样):1, 2, 31, 3, 22, 1, 32, 3, 13, 1, 23, 2, 12.基于以下观察:k 可以放在第1, 阅读全文
posted @ 2013-10-27 15:38 7hat 阅读(298) 评论(0) 推荐(0)
摘要:求x^m 一般方法是 xm = x * xm-1,这样需要做m次乘法,未免过慢。加速方法有两种。1.基于当m为偶数时, xm = (x2)^(m/2) ;当m为奇数时, xm = x * xm-1。显然当m为偶数时m会减半,当m为奇数时,下次就是偶数。m可以很快收敛到0.(^表示幂)2.将m看成二进制串mkmk-1...m1m0,那么xm = xm0*2^0 + m1*2^1 + ... + mk*2^k = xm0*2^0 * xm1*2^1 * ... * xmk*2^k. mi为0或1,假设平均有一半mi为1,即k个,那么总共才只需要做(k+(k/2))次乘法。下面给出代码。第一个方法是 阅读全文
posted @ 2013-10-25 09:22 7hat 阅读(887) 评论(0) 推荐(0)
摘要:计算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) ... 阅读全文
posted @ 2013-10-24 08:58 7hat 阅读(912) 评论(0) 推荐(0)
摘要:利用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 阅读全文
posted @ 2013-10-23 09:20 7hat 阅读(3849) 评论(0) 推荐(0)
摘要:利用指数表和对数表,实现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 阅读全文
posted @ 2013-10-23 09:13 7hat 阅读(1367) 评论(0) 推荐(0)
摘要:目的是找出所有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; ... 阅读全文
posted @ 2013-10-23 09:08 7hat 阅读(1267) 评论(0) 推荐(0)
摘要:最近在学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){ ... 阅读全文
posted @ 2013-10-22 21:36 7hat 阅读(1651) 评论(0) 推荐(0)
摘要:插入排序的一个不错改进。与梳排序类似,希尔排序也用到gap的概念。基本思路是:将原先的一行元素以gap为分界分成几段排成几行,然后按列来用插入排序。不断缩小gap直至1.代码中用到的一个小优化是维基上看到的,据说此比率效率较高,由Knuth提出。另外,还有一个优化基于下面的观察。按照常规思路来说,对于每一个gap,我们应该分别对每一列来做插入排序。但是很显然,不同列之间是不会相互干扰的,因此,在代码中直接从第一列第二个元素开始递增,不断做插入排序。相邻的元素位于不同的列,因此它们并不会影响到彼此,对于同一列的元素,在这一列两个元素之间做了其他什么运算并没影响。这样写代码更加简洁。public 阅读全文
posted @ 2013-10-21 21:31 7hat 阅读(253) 评论(0) 推荐(0)
摘要:冒泡排序的一个不错的改进。与希尔排序有点类似,梳排序在冒泡排序的基础上,提出了gap的概念,使元素的推进快了很多。相当于将原先的一行元素以gap为分界分成几段排成几行,然后按列来用冒泡排序。然后不断缩小gap直至gap为1或元素已经有序(这是冒泡排序的一个特点,凡是改编自冒泡排序(如鸡尾酒排序)都有这个特点,即在遍历过程中就可以确认已经排好序)。public static void combSort(int[] A){ int gap = A.length; boolean unsorted = true; while(gap > 1 || unsorted){ ... 阅读全文
posted @ 2013-10-21 21:26 7hat 阅读(255) 评论(0) 推荐(0)
摘要: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 阅读全文
posted @ 2013-10-21 21:18 7hat 阅读(351) 评论(0) 推荐(0)
摘要:我不知道这个能不能算排序。。。维基上有这个排序名称。。。但我感觉它纯碎在卖萌。。。基本思路:随机打乱数组,然后看看数组有序了没,如果没?继续随机打乱继续看。。。直至有序。神一般的低效。排几十个数不知道要跑多久。。。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... 阅读全文
posted @ 2013-10-21 21:14 7hat 阅读(265) 评论(0) 推荐(0)
摘要:又叫臭皮匠排序。。。在《算法导论》作为反例出现的漂亮但极其低效的排序算法。基本思路是:只要数组长度大于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... 阅读全文
posted @ 2013-10-21 21:13 7hat 阅读(409) 评论(0) 推荐(0)
摘要:比较特别的排序方法。每次先对奇数项的元素与相邻下一位排序,然后对偶数项元素与相邻下一位排序。感觉和冒泡有点类似,只是分开了两次做。public static void oddEvenSort(int[] A){ boolean unsorted = true; while(unsorted){ unsorted = false; for(int i = 1; i A[i+1]){ swap(A, i, i+1); unsorted = true; } } ... 阅读全文
posted @ 2013-10-21 21:07 7hat 阅读(235) 评论(0) 推荐(0)
摘要:又一个高效的排序。这个排序算法的基础是大根堆的操作。主要用到的基本操作是将元素下移至适当位置。大根堆即根结点大于叶子结点,通过将一个普通数组的元素从底层开始不断向下移到适当位置,即构造完毕。在排序的时候,通过每次将第一个元素与“最后”的元素交换,再将根结点移到适当的位置。需要注意的是,这个“最后”是指每趟排序都压缩数组后的长度。另外,由0开始存储元素,左结点是2*i+1,右结点是2*i+2.public static void heapSort(int[] A){ makeHeap(A); for(int i = A.length-1; i > 0; i --){ s... 阅读全文
posted @ 2013-10-21 21:04 7hat 阅读(300) 评论(0) 推荐(0)
摘要:这个排序名字很多,又叫摇晃排序,双向冒泡排序等(见维基),是冒泡排序的一个改进。效率会好一点,但还是差不多。冒泡排序每次向一个方向冒一个泡,而这个每次向后冒泡后再向前冒泡。我对这种写法比较有兴趣,不断压缩“数组长度”直至有序或为1.public static void shakerSort(int[] A){ boolean unsorted = true; int top = A.length-1; int bottom = 0; while(unsorted){ unsorted = false; for(int i = bottom; ... 阅读全文
posted @ 2013-10-21 20:58 7hat 阅读(192) 评论(0) 推荐(0)
摘要:公认的高效排序。这次在原来的基础上加上了随机化的选择划分值,降低最坏时间复杂度。写划分函数可能有点困难,常见的有两种方法。一种是填坑法,另一种就是本文的方法。填坑法的思路是:1.预先保存key值;2.从后往前找,找到一个比key值小的数,然后把这个数填到key值的位置;3.从前往后找,找到一个比key值大的数,然后把这个数填到上面的数的原先位置;4.回到第2步,直至两个下标相遇;5.把key值填到下标相遇位置(原来的数已经填到别的地方了)。我以前也一直在写这种方法,因为思路很简单,但是写起来不够简洁。这次用了另外一种方法,可能有点难理解,但代码相当很简洁。我不知道能不能讲清楚。同样需要用到两个 阅读全文
posted @ 2013-10-21 20:51 7hat 阅读(255) 评论(0) 推荐(0)
摘要:相当高效的稳定排序算法,但空间复杂度较大。典型的分治思想。而将两个有序的数组合并起来也很简单,只需另开一个数组再不断取它们的较小值即可。public static void mergeSort(int[] A){ mergeSortDo(A, 0, A.length-1);}private static void mergeSortDo(int[] A, int low, int high){ if(low < high){ int mid = (low + high) / 2; mergeSortDo(A, low, mid); merg... 阅读全文
posted @ 2013-10-21 20:37 7hat 阅读(215) 评论(0) 推荐(0)
摘要:这次用了比较简洁的方式来写,每次都交换两数而不是单纯移项,可能会慢一点,但代码很漂亮。public static void insertionSort(int[] A){ for(int i = 1; i = 0 && A[j] > A[j+1]; j --){ swap(A, j, j+1); } }}Java 阅读全文
posted @ 2013-10-21 20:33 7hat 阅读(168) 评论(0) 推荐(0)
摘要:基本的排序算法,每次找到一个最值然后交换。值得主要的是,有些人实现的时候每次比较后都交换元素,这其实是不必要的,只需记下下标,在一趟结束后再交换即可。public static void selectionSort(int[] A){ for(int i = 0; i < A.length-1; i ++){ int k = i; for(int j = i+1; j < A.length; j ++){ if(A[j] < A[k])k = j; } if(k != i){ swap(A... 阅读全文
posted @ 2013-10-21 20:30 7hat 阅读(226) 评论(2) 推荐(1)
摘要:冒泡排序可能是很多人第一个学的排序算法,思路简单,实现的方式大同小异。这次收到鸡尾酒排序的启发,尝试用另一种方式来写,感觉更加简单清晰。只要还没排好序,每一趟排序结束后都会产生一个正确的位置,而这时将“数组长度”减1,忽略已经有序的元素。public static void bubbleSort(int[] A){ boolean unsorted = true; int top = A.length-1; while(unsorted){ unsorted = false; for(int i = 0; i A[i+1]){ ... 阅读全文
posted @ 2013-10-21 20:24 7hat 阅读(192) 评论(0) 推荐(0)
摘要:因为课程实验的关系要写排序,心血来潮看看自己能写多少个。再到后来在维基上看看有哪些排序,不知不觉写了十多个(有些排序纯碎在卖萌)。。现在一次过贴个代码先,以后再分类。分别有冒泡排序、选择排序、插入排序、归并排序、快速排序、鸡尾酒排序(摇晃排序或双向冒泡排序)、堆排序、奇偶排序、梳排序、臭皮匠排序(Stooge Sort)、Bogo Sort、 Bozo Sort和希尔排序。import java.util.Random;import java.util.Arrays;public class Sort{ private static void swap(int[] A, int i, i... 阅读全文
posted @ 2013-10-20 14:51 7hat 阅读(249) 评论(0) 推荐(0)
摘要:很久没写博客了,打算换个地方重新开始。旧博客地址如下:http://blog.csdn.net/that163 阅读全文
posted @ 2013-10-20 14:26 7hat 阅读(118) 评论(1) 推荐(0)