// 高效程序的奥秘hacker's delight Henry S. Warren, Jr. 著冯速译

// 第5 章位计数5.4 后缀0 计数

// 假设序列X0, X1, X2, ... 是由Xn+1 = f(Xn) 定义的。如果f 的值域是有限的,那么序列必定是循环的。

// 给定函数f , 循环检测问题就是找到第一个重复出现的元素的下标μ和周期λ.

// 参考:  http://home.pipeline.com/~hbaker1/hakmem/flows.html#item132  LOOP DETECTOR

// Knuth, Donald E. The Art of Computer Programming, Volume 2, Third Edition 3.1 节的问题6

#include "iostream"

#include "bitset"

#include "limits"

#include "time.h"

using namespace std;

#define out2(T) cout<<bitset<numeric_limits<unsigned int>::digits>(T)<<endl;

#define SIZE(T) (numeric_limits<unsigned T>::digits)

bool SHR31(int x)           //逻辑右移位

{

return (unsigned int)x>>31;

}

#define HOUT(x,y,z)    hex_out(x,y,z)

inline void hex(int x)

{

int w = cout.width();

cout << "0x";

cout.width(8); cout.fill('0');

cout << hex << x << "  ";

cout.width(w);

}

inline void hex(unsigned __int64 x)

{

int w = cout.width();

cout << "0x";

cout.width(16); cout.fill('0');

printf("%I64x   ",x);

cout.width(w);

}

void hex_out(int x, int y, int z)

{

hex(x); hex(y); hex(z); cout << endl;

}

int nlz(unsigned int x) {

int n;

if (x == 0) return 32;

n = 1;

if ((x >> 16) == 0) {n = n +16; x = x <<16;}

if ((x >> 24) == 0) {n = n + 8; x = x << 8;}

if ((x >> 28) == 0) {n = n + 4; x = x << 4;}

if ((x >> 30) == 0) {n = n + 2; x = x << 2;}

n = n - (x>>31);

return n;

}

int ntz(unsigned int x)

{

int n;

if (x == 0) return 32;

n = 1;

if ((x & 0x0000FFFF) == 0) {n +=16; x >>= 16;}

if ((x & 0x000000FF) == 0) {n += 8; x >>= 8;}

if ((x & 0x0000000F) == 0) {n += 4; x >>= 4;}

if ((x & 0x00000003) == 0) {n += 2; x >>= 2;}

return n - (x & 1);

}

// 平方取中

int f(int a)

{

return (a*a / 120) % 14400;

}

// 这里分五步论证算法的正确性:

// 0. f值域有限,则f 函数是循环,参考knuth 的证明

// 1. 设前面存的T[] 最大位置p, 现在查询最大位置kmax, 总有p = kmax

//    证:先证p 不小于且不大于kmax, p 存放的位置每次最大发生在2^i 处,

//         如: 10, 100, 1000, 10000 ...

//         设位长W = 8, 则 1000B 处是交界, ntz(1000B) = 3; kmax = 8-1 - nlz(1000B) = 7 - 4 = 3; 若i < 1000B, kmax <= p

//         若i > 1111B , 如i = 10000B, 则p = 4, kmax = 8-1 - nlz(10000B) = 4, kmax = p, 即kmax 随p 更新

//         又p 取所有位置的最大位置所以总有p = kmax, 不会造成访问越界,也不会造成访问遗漏.

// 2. T[] 数组有些元素总会被后来的元素覆盖, 但个别元素在一个周期内不会被覆盖.如果存在这种元素(称为异元素),

//     则总能在第二个周期λ中检测到循环

//     证:如奇数,由于ntz(奇数) = 0, 前一个奇数总被后一个奇数覆盖

//         若偶数,是不是在一个周期λ内有偶数不被覆盖,且不覆盖别的偶数呢?这一点很重要, 设这种偶数为异元素

//         因为被覆盖的元素在第二个周期都会反过来覆盖先前覆盖它的元素,

//         而到第二个周期λ检测中,这种异元素不会被反覆盖,当再一次走到这个值时,就可以检测到相同,

//         所以总能在第二个周期λ中检测到循环

// 3. 这种异元素总是存在的

//     证:举例λ= 10110101B, 从μ位置开始循环, 如果μ= 0, 则10000000B 位置为异元素, 因为ntz(10000000B)

//         是i < 11111111B 中最大的了, 如果 μ= 01001011B,  μ+ λ= 100000000B 这个元素独一无二的,

//         在下一个周期内μ+ λ+ λ< 1000000000B, 不可能有更大的p, 又p 先于kmax 更新,所以在一个周期内

//         这种独一无二的元素总是存在的

// 4. 对于周期λ和μ的求解也就迎刃而解了,可参考ITEM 132 和下面的程序

// 找出序列 的周期 λ (lambda) 和 开始位置 μ 的上下界 mu_l , mu_u

void ld_Gosper(int (*f)(int), int X0, int *mu_l, int *mu_u, int *lambda)

{

int Xn, k, m, kmax, n, lgl;

int T[33];

T[0] = X0;

Xn = X0;

for (n = 1; ; n++) {

Xn = f(Xn);

kmax = 31 - nlz(n);                       // Floor(log2 n).

for (k = 0; k <= kmax; k++) {

if (Xn == T[k]) goto L;

}

T[ntz(n+1)] = Xn;                    // No match.

}

L:

// Compute m = max{i | i < n and ntz(i+1) = k}.

m = ((((n >> k) - 1) | 1) << k) - 1;

*lambda = n - m;

lgl = 31 - nlz(*lambda - 1);              // Ceil(log2 lambda) - 1

*mu_u = m;                                     // Upper bound on mu.

*mu_l = m - __max(1, 1 << lgl) + 1;       // Lower bound on mu.

}

void test1();

void main()

{

test1();

}

void test2()

{

int (*p)(int) = f;

int X0 = 32690;

int *mu_l = new int; int *mu_u = new int; int *lambda = new int;

ld_Gosper(p, X0, mu_l, mu_u, lambda);

cout << (*mu_l) << " " << (*mu_u) << " " << (*lambda) << endl;

delete mu_l; delete mu_u; delete lambda;

}

void test1()

{

int (*p)(int) = f;

int X0 = 286;//123456;//2375;

int *mu_l = new int; int *mu_u = new int; int *lambda = new int;

//   ld_Gosper(p, X0, mu_l, mu_u, lambda);

//   cout << (*mu_l) << " " << (*mu_u) << " " << (*lambda) << endl;

int max = 0; int q = X0;

for (int j = 1; ;j++) {

X0 = j;

ld_Gosper(p, X0, mu_l, mu_u, lambda);

if (*lambda >= max) { max = *lambda; q = X0;}

if (j >= 0x7FFF) break;

}

ld_Gosper(p, q, mu_l, mu_u, lambda);

cout << (*mu_l) << " " << (*mu_u) << " " << (*lambda) << endl << endl;

X0 = q;

for (int i = 0; i < 50; i++) {

cout << X0 << endl;

X0 = p(X0);

}

delete mu_l; delete mu_u; delete lambda;

}

Gosper 的序列 循环检测相关推荐

  1. 动脉自旋标记磁共振成像在灌注和侧支循环检测的研究进展

    随着2015年国际医学磁共振学会(ISMRM)的灌注研究小组发表的共识声明,以及EU-COST的"ASL in dementia"研究中关于动脉自旋标记磁共振成像(ASL)在临床中 ...

  2. 基于深度模型的日志序列异常检测

    基于深度模型的日志序列异常检测 ​ 日志异常检测的核心是利用人工智能算法自动分析系统日志来发现并定位故障.根据送入检测模型的数据格式,日志异常检测算法模型分为序列模型和频率模型,其中序列模型又可以分为 ...

  3. (80)FPGA面试题-请画出序列“1101 “检测状态转移图

    1.1 FPGA面试题-请画出序列"1101 "检测状态转移图 1.1.1 本节目录 1)本节目录: 2)本节引言: 3)FPGA简介: 4)FPGA面试题-请画出序列" ...

  4. floyd算法 每一层循环_链接列表循环检测– Floyd的循环查找算法

    floyd算法 每一层循环 In this tutorial, we'll be discussing a very popular algorithm which is used to detect ...

  5. java socket 循环读取_java socket tcp(服务器循环检测)

    刚才看了下以前写了的代码,tcp通信,发现太简单了,直接又摘抄了一个,运行 博客:http://blog.csdn.net/zhy_cheng/article/details/7819659 优点是服 ...

  6. 重迭式三段式状态机序列检测器-检测10110110

    重迭式三段式状态机序列检测器-检测10110110 要求:序列检测器 clk input clock input rst_n input asynchronous reset, low active ...

  7. skynet源码阅读7--死循环检测

    在使用skynet开发时,你也许会碰到类似这样的警告:A message from [ :0100000f ] to [ :0100000a ] maybe in an endless loop (v ...

  8. 序列循环oracle,Oracle创建序列及循环自增取值问题-Oracle

    Oracle创建序列及循环自增取值问题 用sys登陆Oracle SQL> conn sys/root as sysdba; 创建sequence SQL> create sequence ...

  9. 基于GMM模型的Waving Trees序列前景检测

    实验内容 本次实验主要通过运动python语言实现了一种基于混合高斯模型(GMM)的前景检测算法,其思想主要参考论文[4][7][8]. 本次实验使用WavingTrees[9]数据来进行实验.该数据 ...

最新文章

  1. JQuery-- 获取元素的宽高、获取浏览器的宽高和垂直滚动距离
  2. Day 3: Flask —— 使用Python和OpenShift进行即时Web开发
  3. 使用Apache CXF开发RESTful服务
  4. CF888G XOR-MST 最小异或生成树
  5. ubuntu16.04 kinetic外接Intel Realsense D435i配置教程
  6. CentOS 7 安装Mono 和 MonoDevelop
  7. TASLP | 从判别到生成:基于对比学习的生成式知识抽取方法
  8. Hyper-v中安装centos网卡故障
  9. 18. web robot
  10. 三、VueJs 填坑日记之项目文件认识
  11. 人人开源项目搭建到服务器,人人开源系列项目介绍以及环境搭建
  12. java生成docx文件、pdf文件、docx转pdf、docx转图片 pdf转图片工具
  13. 保研经历-清华计算机、北大、中科院计算所
  14. 基于Web服务的物联网-WoT(Web of Things)
  15. odi lkm mysql_Oracle ODI系列之一(ODI知识模块)
  16. Android 闹钟demo
  17. IOS开发之免费证书+不越狱真机调试
  18. ABAP inner join 性能影响
  19. 智慧物联下主机加固安全解决方案分析
  20. 2016-2017年江苏省留学生创业优惠政策及创业补贴

热门文章

  1. 本质矩阵svd分解_SVD推荐系统
  2. mybitas oracle.sql.clob,Oracle使用简单函数
  3. AI:2020年6月22日北京智源大会演讲分享之09:50-10:40 Anil教授《Pattern Recognition: Statistics to Pattern Recognition》
  4. 成功解决ModuleNotFoundError: No module named 'keras_resnet'
  5. CV之FR:计算机视觉之人脸识别(Face Recognition)方向的简介、代码实现、案例应用之详细攻略
  6. CV:Win10下深度学习框架安装之Tensorflow/tensorflow_gpu+Cuda+Cudnn(最清楚/最快捷)之详细攻略(图文教程)
  7. LeetCode Implement Trie(Prefix Tree)
  8. Select 多个表并且相关联转置
  9. [总结] 动态DP学习笔记
  10. 实验 3:备份和还原配置文件