算法篇-13-随机化-线性同余&主元素问题&N皇后问题&素数测试
2016-12-28 12:39
435 查看
本系列所有代码https://github.com/YIWANFENG/Algorithm-github
1..这类算法所得到的往往是近似解。
2.近似解的精度随着计算时间的增加而不断提高。
蒙特卡罗算法:
1.求问题的准确解,但得到的解不一定正确。
2.计算时间越长,解的正确性越高。
拉斯维加斯算法:
1.求正确解,但可能得不到任何解。
2.计算时间越长,得到正确解几率越高。
舍伍德算法:
1.总可求的一解,且所求解一定正确。
2.非避免算法最坏,而是消除最坏与特定实例之间的关联。
X(n+1) = (a * X(n) + c) % m这样的公式,其中:
模m, m > 0
系数a, 0 < a < m
增量c, 0 <= c < m
原始值(种子) 0 <= X(0) < m
其中参数c, m, a比较敏感,或者说直接影响了伪随机数产生的质量。
由上述公式得出x(n+1)后右移16位即得到一个0-65535之间的随机数。
(高16位随机性较低16位好)
设T[1:n]是一个含有n个元素的数组(集合)。当 | {i | T[i]=x} | > n/2 时,称元素x是数组T的主元素。判断一数组是否含有主元素。
算法思路分析以及相关公式:
蒙特卡洛算法,随机从数组中取一个数来测试其是否是该数组的主元素。
一次随机测试很可能出错,在这里我们采用多次取样判断来减小误差。
若数组含有主元素,则返回true的概率是p (p>1/2)。2次调用返回true的概率是
P+(1-P)*P, = (1-P)^2 > 3/4,如果需要更高准确度则重复更多次数。
算法分析与相关公式:
对于n后问题的任何一个解而言,每一个皇后在棋盘上的位置无任何规律,不具有系统性,而更象是随机放置的。在棋盘上相继的各行中随机地放置皇后,并注意使新放置的皇后与已放置的皇后互不攻击,直至n个皇后均已相容地放置好,或已没有下一个皇后的可放置位置时为止。
算法思路分析以及相关公式:
Wilson定理:对于给定的正整数n,判定n是一个素数的充要条件是(n-1)! -1(mod n)。
费尔马小定理:如果p是一个素数,且0<a<p,则a^(p-1)(mod p)。
二次探测定理:如果p是一个素数,且0<x<p,则方程x^21(mod p)的解为x=1,p-1。
Carmichael数:费尔马小定理是素数判定的一个必要条件。满足费尔马小定理条件的整数n未必全是素数。有些合数也满足费尔马小定理的条件,这些合数称为Carmichael数。前3个Carmichael数是561,1105,1729。Carmichael数是非常少的,在1~100000000的整数中,只有255个Carmichael数。
四中随机化算法
数值随机化算法:1..这类算法所得到的往往是近似解。
2.近似解的精度随着计算时间的增加而不断提高。
蒙特卡罗算法:
1.求问题的准确解,但得到的解不一定正确。
2.计算时间越长,解的正确性越高。
拉斯维加斯算法:
1.求正确解,但可能得不到任何解。
2.计算时间越长,得到正确解几率越高。
舍伍德算法:
1.总可求的一解,且所求解一定正确。
2.非避免算法最坏,而是消除最坏与特定实例之间的关联。
线性同余产生伪随机数
算法思路分析以及相关数学公式:X(n+1) = (a * X(n) + c) % m这样的公式,其中:
模m, m > 0
系数a, 0 < a < m
增量c, 0 <= c < m
原始值(种子) 0 <= X(0) < m
其中参数c, m, a比较敏感,或者说直接影响了伪随机数产生的质量。
由上述公式得出x(n+1)后右移16位即得到一个0-65535之间的随机数。
(高16位随机性较低16位好)
#include <iostream> #include <time.h> //线性同余产生伪随机数 using namespace std; class CRandom { private: unsigned long rand_seed; //随机数种子 public: CRandom(unsigned long s = 0) { if(!s) rand_seed = time(0); else rand_seed = s; } unsigned long Random(unsigned long n) { //0-n-1之间的随机数 const unsigned long multiplier = 1194211693L; const unsigned long adder = 15465L; rand_seed = multiplier*rand_seed + adder; return (rand_seed>>16) % n; } double fRandom(void) { //产生0-1之间的随机实数 const unsigned long large_number = 0x10000; return Random(large_number) / double(large_number); } }; int main() { CRandom rnd; int i,n=100000; int m[10]; for(i=0;i<10;++i) m[i]=0; //查看生成随机数的分布 for(i=0;i<n;i++) m[rnd.Random(1000)/100]++; for(i=0;i<10;++i) cout<<m[i]/(double)n<<endl; cin.get(); return 0; }
主元素问题
题目:设T[1:n]是一个含有n个元素的数组(集合)。当 | {i | T[i]=x} | > n/2 时,称元素x是数组T的主元素。判断一数组是否含有主元素。
算法思路分析以及相关公式:
蒙特卡洛算法,随机从数组中取一个数来测试其是否是该数组的主元素。
一次随机测试很可能出错,在这里我们采用多次取样判断来减小误差。
若数组含有主元素,则返回true的概率是p (p>1/2)。2次调用返回true的概率是
P+(1-P)*P, = (1-P)^2 > 3/4,如果需要更高准确度则重复更多次数。
#include <time.h> #include <stdlib.h> #include <math.h> #include <iostream> //主元素问题-- 蒙特卡洛算法 using namespace std; template <class T_> bool Majority(const T_ *t,int n) { srand(time(0));//取消后正确几率下降 int i = rand()%n; T_ x = t[i]; int k =0; for(int j=0;j<n;++j) { if(t[j]==x) k++; } return (k>n/2); } template <class T_> bool MajorityMC(const T_*t,int n,double e) { //e允许的最大错误几率 int k =ceil(-log(e)/log(2.0)); for(int i=1;i<=k;++i) { if(Majority(t,n)) return true; } return false; } int main() { srand(time(0)); int i,n = 10000; int *a = new int ; for(i=0;i<n;++i) a[i] = i+1; int counter = 0 ; while (counter<n/2+1) { i = rand()%n; if(a[i]!=0) { a[i]=0; ++counter; } } for(i = 0;i<40;++i) { if(MajorityMC(a,n,0.1)) cout<<true<<endl; else cout<<false<<endl; } cin.get(); delete []a; return 0; }
N皇后问题
N皇后问题,Las Vegas 算法。算法分析与相关公式:
对于n后问题的任何一个解而言,每一个皇后在棋盘上的位置无任何规律,不具有系统性,而更象是随机放置的。在棋盘上相继的各行中随机地放置皇后,并注意使新放置的皇后与已放置的皇后互不攻击,直至n个皇后均已相容地放置好,或已没有下一个皇后的可放置位置时为止。
#include <time.h> #include <stdlib.h> #include <math.h> #include <iostream> //nqueue - Las Vegas using namespace std; class NQueue_Las_Vegas { private: int *y; //当前行上皇后可放置的位置 bool Place(int k) { //验证第k行皇后位置是否合理 for(int i=1; i<k; ++i) { if((k-i)==abs(x[i]-x[k]) || x[i]==x[k]) return false; } return true; } bool Backtrack(int t) { //回溯法 if(t>n) return true; else { for(int i=1;i<=n;++i) { x[t] = i; if(Place(t) && Backtrack(t+1)) return true; } } return false; } bool QueuesLV(int m) { //随机放置m个皇后的Las Vegas算法 int k = 1; int count = 1; while(k<=m && count>0) { count=0; for(int i=1;i<=n;++i) { x[k]=i; if(Place(k)) y[count++] = i; } if(count>0) x[k++] = y[rand()%count]; } return count>0; } public: int n; int *x; void Solve(int num_loops) { y = new int[n+1]; int m = 5; if(n>15) m = n-15; bool found = false; for(int i=1;i<num_loops;++i) { if(QueuesLV(m)) { if(Backtrack(m+1)) { found = true; break; } } } if(found) { for(int i=1;i<=n;++i) cout<<x[i]<<' '; cout<<endl; } else { cout<<"No Answer"<<endl; } delete [] y; } }; int main() { NQueue_Las_Vegas nq; nq.n = 8; nq.x = new int[nq.n+1]; for(int i=0;i<20;++i) nq.Solve(10) ; cin.get(); delete [] nq.x; return 0; }
素数测试
--蒙特卡洛算法算法思路分析以及相关公式:
Wilson定理:对于给定的正整数n,判定n是一个素数的充要条件是(n-1)! -1(mod n)。
费尔马小定理:如果p是一个素数,且0<a<p,则a^(p-1)(mod p)。
二次探测定理:如果p是一个素数,且0<x<p,则方程x^21(mod p)的解为x=1,p-1。
Carmichael数:费尔马小定理是素数判定的一个必要条件。满足费尔马小定理条件的整数n未必全是素数。有些合数也满足费尔马小定理的条件,这些合数称为Carmichael数。前3个Carmichael数是561,1105,1729。Carmichael数是非常少的,在1~100000000的整数中,只有255个Carmichael数。
#include <time.h> #include <stdlib.h> #include <math.h> #include <iostream> //素数测试 --蒙特卡洛算法 using namespace std; void PowerAndPrimeTest(unsigned int a,unsigned int p,unsigned int n, unsigned int &result,bool &composite) { //计算power(a,p) mod n ,同时实施对n的二次探测 //result计算结果 composite是否为合数 unsigned int x; if(p==0) result = 1; else { PowerAndPrimeTest(a,p/2,n,x,composite); result = (x*x)%n; if(result==1 && x!=1 && x!=n-1) composite = true; //计算结果 if(p%2==1) //p是奇数 result = (result*a)%n; } } bool PrimeTestMC(unsigned int n,unsigned int k) { //检测n是否为素数 //重复调用k次蒙特卡洛算法 unsigned int a,result; bool composite = false; if(n<5) { if(n==2 || n == 3) return true; return false; } for(int i=1;i<=k;++i) { //下面这句决定5以下素数测试有问题 a = rand()%(n-3)+2 ; PowerAndPrimeTest(a,n-1,n,result,composite); if(composite || (result!=1)) return false; } return true; } bool PrimeTest(unsigned int n) { if(n==1) return false; else if(n==2) return true; unsigned int i,m = sqrt(n); for(i=2;i<=m;++i) if(n%i==0) return false; return true; } int main() { unsigned int n = 1194211693L; for(int i=2000;i<5000;++i) if(PrimeTest(i)) { cout<<i<<endl; n=i; break; } for(int i=0;i<20;++i) { if(PrimeTestMC(n,4)) cout<<true<<endl; else cout<<false<<endl; } cin.get(); return 0; }
相关文章推荐
- 0049算法笔记——【随机化算法】蒙特卡罗算法,主元素问题,素数测试问题
- 0049算法笔记——【随机化算法】蒙特卡罗算法,主元素问题,素数测试问题
- 【随机化算法】蒙特卡罗算法,主元素问题,素数测试问题
- 0049算法笔记——【随机化算法】蒙特卡罗算法,主元素问题,素数测试问题
- 测试的时候浏览出现 "WebDev.WebServer.exe 遇到问题需要关闭。我们对此引起的不便表示抱歉。
- android 真机部署测试 "INSTALL_FAILED_MEDIA_UNAVAILABLE” 问题
- 【iOS开发必收藏】详解iOS应用程序内使用IAP/StoreKit付费、沙盒(SandBox)测试、创建测试账号流程!【2012-12-11日更新获取"产品付费数量等于0的问题"】
- RabbitMQ&nbsp;测试问题
- 【iOS开发必收藏】详解iOS应用程序内使用IAP/StoreKit付费、沙盒(SandBox)测试、创建测试账号流程!【2012-12-11日更新获取"产品付费数量等于0的问题"】
- 反驳"MySQL InnoDB (不行)的性能问题",千万级别记录来测试说明
- 【iOS开发必收藏】详解iOS应用程序内使用IAP/StoreKit付费、沙盒(SandBox)测试、创建测试账号流程!【2012-12-11日更新获取"产品付费数量等于0的问题"】
- 在线重定义表的测试和问题 &lt;转&gt;
- linux下查找字符串&mysql-为magento性能测试修改innodb的innodb_buffer_pool_size而引发的问题
- 在MacBook 13“机器上无法安装"Boot Camp x64"驱动程序问题的处理
- 【iOS开发必收藏】详解iOS应用程序内使用IAP/StoreKit付费、沙盒(SandBox)测试、创建测试账号流程!【2012-12-11日更新获取"产品付费数量等于0的问题"】
- WEbService服务端-用Axis客户端测试遇到的问题Exception in thread "main" AxisFault
- .NET转换xslt xml 时某些元素包含xmlns=""的问题
- <button> 元素点击后刷新的问题
- hdu 2553 N皇后问题<java>
- 【iOS开发必收藏】详解iOS应用程序内使用IAP/StoreKit付费、沙盒(SandBox)测试、创建测试账号流程!【2012-12-11日更新获取"产品付费数量等于0的问题"】