zoukankan      html  css  js  c++  java
  • Pollard Rho大质数分解学习笔记

    目录

    问题

    给定n,要求对n质因数分解
    普通的试除法已经不能应用于大整数了,我们需要更快的算法

    流程

    大概就是找出(n=c*d)
    如果(c)是素数,结束,不是继续递归处理。
    具体一点的话
    1.先对n进行(miller\_rabin)测试,是素数就直接结束了
    如果不会的话,看我前篇博客的介绍吧
    为何还要多写个(miller\_rabin),他没有非平凡因子,他要保证复杂度?
    2.随机基底a和c,生成序列(x_{0}=a,x_{i}=x_{i-1}^{2}+c(mod n)),可以认为({x_{i}})是有循环节的随机序列(rho就是密度的那个符号,长得很像是不是)
    3.若出现((x_{i}-x_{2i+1},n)≠1),停止算法,令(d=(x_{i}-x_{2i+1},n)),若(d≠n),那d就是n的非平凡因子,n被分为d和n/d相乘的结果,递归下去继续分解
    4.若d=n,重选基底a和c,重复过程(出现循环了)

    刘汝佳先生说:想象一下,假设有两个小孩子在一个“可以无限向前跑”的跑道上赛跑,同时出发。但其中一个小孩的速度是另一个的两倍。如果跑道是直的,跑得快的小孩永远在前面;但如果跑道有环,则跑得快的小孩将“追上”跑得慢的小孩。

    算法复杂度(O(n^{ frac {1}{4} }*pro))
    具体的我也不知道咋证

    代码

    #include <bits/stdc++.h>
    
    using namespace std;
    const int maxn = 10005;
    typedef long long LL;
    
    LL fpm(LL a, LL k, LL p) //calc a^k % p
    {
    	LL res = 1;
    	for (; k ; k >>= 1, a = a * a % p)
    		if (k & 1) res = a * res % p;
    	return res;		
    }
    
    int prime[] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29};
    bool detective(LL a, LL n)
    {
    	int r = 0; LL d = n - 1; // n - 1 = 2 ^ r * d
    	while (d % 2 == 0) d >>= 1, ++r;
    	for (LL x = fpm(a, d, n), y; r ; r--)
    	{
    		y = x * x % n;
    		if (y == 1)
    		{
    			if (x == 1) return true;
    			if (x == n - 1) return true;
    			return false;
    		}
    		x = y;
    	}
    	return false;
    }
    bool miller_rabin(LL n)
    {
    	for (int i = 0; i < 10; i++)
    	{
    		if (n == prime[i]) return true;
    		if (n % prime[i] == 0) return false;
    		if (!detective(prime[i], n)) return false;
    	}
    	return true;
    }
    
    vector<LL> res;
    int irand() {return rand() << 15 ^ rand();}
    LL irand(LL n) {return (((LL) irand()) << 30 ^ irand()) % n;}
    LL mul(LL a, LL b, LL n) {return (a * b - (LL) ((long double) a * b / n + 1e-9) * n) % n;}
    LL rho(LL n)
    {
    	LL a = irand(n), c = irand(n);
    	LL x = a, y = (mul(a, a, n) + c) % n;
    	LL z = x > y ? x - y: y - x;
    	LL d = __gcd(z, n);
    	while (d == 1)
    	{
    		x = (mul(x, x, n) + c) % n;
    		y = (mul(y, y, n) + c) % n;
    		y = (mul(y, y, n) + c) % n;
    		z = x > y ? x - y: y - x;
    		d = __gcd(z, n);
    	}
    	return d;
    }
    void pollard_rho(LL n)
    {
    	if (n == 1) return ;
    	if (miller_rabin(n)) {res.push_back(n); return ;}
    	LL d = n; while (d == n) d = rho(n);
    	pollard_rho(d); pollard_rho(n / d);
    }
    int main()
    {
    	pollard_rho(997 * 131ll * 6ll * 50ll * 79ll * 97 * 12132);
    	for (auto x: res) cerr << x << " " ;
    }
    
    

    生日悖论

    (当然,我们这里的一年是稳定365天,和我们不一样)
    23个人中至少有一对两个人生日相同的概率在一半以上,感觉不可思议吧,与我们自我感觉的有很大差异,其实,当我们看到“有人生日相同”时,下意识地会用“与我生日相同”去推测,直觉就让我们直觉产生了“两人生日相同”概率很小。理性计算的结果与日常经验产生了如此明显的矛盾,所以叫做“生日悖论”。
    可以说,直觉没有错,错的是我们没有正确地去理解问题。因此,当我们剥开直觉的谎言,看清事实的那一刻,才会觉得如此不可思议。
    我们的问题是“任意两个人的生日相同的概率”(所以要理性分析呀qwq)。
    我们讨论两个人生日相同的情况。
    总概率是365*365,生日不同的情况(365*364)
    那生日相同的情况就是 (frac{365*365-365*364}{365*365}=frac{1}{365})
    四个人同理(frac{365^4-frac{365!}{361!}}{365^4})
    再大一点可以用long double 计算,可以算出23人时概率就大于一半了

    end

    鸣谢

  • 相关阅读:
    读財报:交易额增长111%的京东,为毛还是亏?
    HDU 1548 A strange lift 搜索
    linux两台server远程copy文件
    Nginx 反向代理、负载均衡、页面缓存、URL重写及读写分离具体解释
    js事件防止冒泡
    LeetCode Rotate Array
    ARM架构授权和IP核授权有什么不一样啊?
    Linux系统结构 详解
    mount -o
    ARM开发板系统移植-----u-boot的编译
  • 原文地址:https://www.cnblogs.com/dsrdsr/p/10354459.html
Copyright © 2011-2022 走看看