挑战性题目DSCT501:大整数因子分解
挑战性题目DSCT501:大整数因子分解
问题描述
大整数质因子分解。
题解
笑死,数据结构课背包都不讲,却给学生出泼辣肉,我的心里只有感恩。
因为本题的数据范围巨大,传统的O(n)O(\sqrt n)O(n)的质因数分解已经不适用,需要另外的算法。
首先是质数探测算法——Miller_rabin算法,其基于费马小定理,若p是质数,ap−1≡1(modp)a^{p-1}\equiv1\left(\mod p\right)ap−1≡1(modp)。同时,若ppp为质数,x2≡1(modp)x^2\equiv1\left(\mod p\right)x2≡1(modp)可推出x=1orp−1x=1\ or\ p-1x=1 or p−1。所以,我们要判断一个质数是否是质数时,先套费马小定理判断,如果符合费马小定理,再判断(n−1)/2(n-1)/2(n−1)/2是否满足上述第二个性质,如果对于一个预先设定的质数集合p[]
(本人使用的集合为2,325,9375,28178,450775,9780504,17952650222, 325, 9375, 28178, 450775, 9780504, 17952650222,325,9375,28178,450775,9780504,1795265022),数字nnn均通过上述检验,则认为其是质数。
之后,再利用大整数因数探测算法Pollar_Rho算法,若正整数nnn至少有一个因子不超过n\sqrt nn,设它任意一个因子为ppp,若随机生成ppp以内的数,期望O(p)O\left(\sqrt p\right)O(p)次就可以随机到两个一样的数。
随机生成[1,n][1,n][1,n]的正整数,它们modpmod\ pmod p下可近似看做在[1,p][1,p][1,p]内随机,随机生成两个数a,b(b>a)a,b(b>a)a,b(b>a),若b=a(modp)→p∣(b−a)→gcd(n,b−a)≥pb=a(mod\ p)\rightarrow p|(b-a)\rightarrow gcd(n,\ b-a)\geq pb=a(mod p)→p∣(b−a)→gcd(n, b−a)≥p
那么gcd(n,b−a)gcd\left(n,b-a\right)gcd(n,b−a)必为nnn的一个大于111的因数。令随机数这样生成:a0=C,f(x)=x2+C,ai=f(ai−1)a_0=C,f\left(x\right)=x^2+C,a_i=f\left(a_{i-1}\right)a0=C,f(x)=x2+C,ai=f(ai−1)即跳一步就套用一次f(x)f\left(x\right)f(x)。这样做的好处是:若ax=ay(modp)→ax+1−ay+1=f(ax)−f(ay)=(ax+ay)(ax−ay)=0(modp)a_x=a_y\left(\mod p\right)\rightarrow a_{x+1}-a_{y+1}=f\left(a_x\right)-f\left(a_y\right)=\left(a_x+a_y\right)\left(a_x-a_y\right)=0(\mod p)ax=ay(modp)→ax+1−ay+1=f(ax)−f(ay)=(ax+ay)(ax−ay)=0(modp) 即任一距离为ddd的随机数modp\mod pmodp相同,所有距离为ddd的随机数modp\mod pmodp都相同,这样只需要检查其中一个即可。
免除记忆化:维护两个数,一个数每次调用两次fff,一个每次调用一次,如果走完了环,最后两个数一定会相遇。同时也枚举了所有距离。
优化:瓶颈在于gcdgcdgcd,可以减少取gcd(n,∣a−b∣)gcd\left(n,\left|a-b\right|\right)gcd(n,∣a−b∣)的次数,将所有的∣a−b∣\left|a-b\right|∣a−b∣乘起来,累计128128128次后再与nnn取gcdgcdgcd(前提是a,ba,ba,b还没有在环上相遇),复杂度约为O(n1/4)O(n^{1/4})O(n1/4)。
代码
感谢我的超人——Rockdu提供的泼辣肉模板,说实话我也没怎么搞懂,以后有缘再学。
#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define LL long long
using namespace std;LL n;namespace NT {LL gcd(LL a, LL b) {return b ? gcd(b, a % b) : a;}LL mul(LL a, LL b, LL m) {LL s = a * b - (LL)((long double)a * b / m + 0.5) * m;return s < 0 ? s + m : s;}LL fpow(LL x, LL a, LL m) {LL ans = 1;while(a) {if(a & 1) ans = mul(ans, x, m);x = mul(x, x, m), a >>= 1;}return ans;}
}namespace Miller_Rabin {using namespace NT;LL p[15] = {2, 325, 9375, 28178, 450775, 9780504, 1795265022};int detect(LL n, LL a) {if(n == a) return 1;if(a % n == 0) return 1;LL now = n - 1, lst = 1;if(fpow(a, now, n) != 1) return 0;while(!(now & 1)) {now /= 2;LL p = fpow(a, now, n);if(lst == 1 && p != 1 && p != n - 1)return 0;lst = p;}return 1;}LL MR(LL n) {if(n < 2) return 0;for(int i = 0; i < 7; ++i) {if(!detect(n, p[i])) return 0;}return 1;}
}namespace Pollard_Rho {using namespace NT;using namespace Miller_Rabin;LL f(LL x, LL C, LL p) {return (mul(x, x, p) + C) % p;}LL Rand() {return (rand() << 15) + rand();}LL Randll() {return (Rand() << 31) + Rand();}LL PR(LL n) {if(n == 4) return 2;if(MR(n)) return n;while(1) {LL C = Randll() % (n - 1) + 1;LL s = 0, t = 0;LL acc = 1;do {for(int i = 1; i <= 128; ++i) {t = f(f(t, C, n), C, n);s = f(s, C, n);LL tmp = mul(acc, abs(t - s), n);if(s == t || tmp == 0)break;acc = tmp;}LL d = gcd(n, acc);if(d > 1) return d;} while(s != t);}}typedef pair<LL, int > pii;vector<pii > DCOMP(LL n) {vector<pii > ret;while(n != 1) {LL p = PR(n);while(!MR(p)) p = PR(p);int c = 0;while(n % p == 0) n /= p, ++c;ret.push_back(make_pair(p, c));}return ret;}
}
void out(long long x){if(x>9)out(x/10);putchar(x%10+'0');}
int main(int argc,char* argv[]) {srand(19260817);LL n=atoll(argv[1]);if(n==1)return 0; auto ans = Pollard_Rho::DCOMP(n);out(ans[0].first);ans[0].second--;for(auto i : ans)while(i.second--) putchar('*'),out(i.first);return 0;
}
挑战性题目DSCT501:大整数因子分解相关推荐
- 公钥密码系统主要依赖的三种数学难题:1.大整数因子分解问题 2.离散对数问题 (DLP问题) 3. 椭圆曲线上的离散对数问题(ECDLP)
公钥密码系统主要依赖下面三种数学难题 1.大整数因子分解问题,如 RSA 系统 1.数理 2.流程 2.离散对数问题 (DLP问题) 1.数理: 2.流程:(EIGamal 公钥系统) 3. 椭圆曲线 ...
- c语言程序做四则运算还要余数,大整数四则运算 高质量C语言程序.doc
大整数四则运算 高质量C语言程序 设计题目: 大整数的四则运算 1. 功能简介:编写出实现大整数之间相加,相减,相乘,相除的程序,并输出计算结构. 课程设计要求:采用模块化程序设计 源程序中应有足够的 ...
- C语言 大整数运算(加、减、乘)
题目:大整数计算 背景介绍: 大整数一般指超过十尾的十进制整数,假定不超过五十位.这类大整数在C语言系统中因超界溢出而不能直接表达或计算. 实现方法: 以字符串形式输入.输出和存放大整数,计算时可以将 ...
- NOI1.13.47 大整数除法 题解(C++)
NOI1.13.47 大整数除法 题解(C++) 这题一看题目就知道绝非普通的long long 或 int .这可是高精度呀. 题目 47:大整数除法 总Time Limit: 1000ms Mem ...
- 循环相乘取整法C语言,华为OJ机试题目:两个大整数相乘(纯C语言实现两个大整数相乘,两种方法实现大数相乘)...
题目描述: 输出两个不超过100位的大整数的乘积. 输入: 输入两个大整数,如1234567 123 输出: 输出乘积,如:151851741 样例输入: 1234567 123 样例输出: 1518 ...
- 整数判重、大整数Hash
大整数Hash 总是听高届的大佬说,一个字符串Hash,能搞出大部分的字符串题,Hash真的有那么神吗? 答:是的 近来,参加很多NOIP模拟赛,其中一场设计判断大整数是否存在偷懒了一下,开了一个ma ...
- 【PAT甲级 大整数BigInteger】1065 A+B and C (64bit) (20 分) Java 全部AC
题目 在有些方面,比如大整数的处理,不得不佩服Java,好用没的说,像开挂一样 题解 Java import java.math.BigInteger; import java.util.Scanne ...
- LeetCode 1985. 找出数组中的第 K 大整数(排序)
文章目录 1. 题目 2. 解题 1. 题目 给你一个字符串数组 nums 和一个整数 k . nums 中的每个字符串都表示一个不含前导零的整数. 返回 nums 中表示第 k 大整数的字符串. 注 ...
- 信奥中的数学:前缀和与差分、大整数开方技巧
[算法2-1]前缀和与差分 [算法2-1]前缀和与差分 - 题单 - 洛谷 前缀和与差分 图文并茂 超详细整理(全网最通俗易懂) 前缀和与差分 图文并茂 超详细整理(全网最通俗易懂)_林深不见鹿 的博 ...
- 信息学奥赛一本通 1171:大整数的因子 | OpenJudge NOI 1.6 13:大整数的因子
[题目链接] ybt 1171:大整数的因子 OpenJudge NOI 1.6 13:大整数的因子 [题目考点] 1. 高精度 考察:高精模低精 高精度计算讲解 [解题思路] 先把参与运算的数字当成 ...
最新文章
- 2021年春季学期-信号与系统-第六次作业参考答案-第七小题
- 20位数字转化成6位不重复码_人力资源管理浅析身份证数字号码编排常识甄别年龄、性别、籍贯…...
- html5家谱资源网,免费家谱系统(ASP,Access,CSS,html5)
- Asp.Net 数据分页
- 对于短信平台呼叫状态机的调查
- java Calendar
- c++ eos智能合约开发_[EOS智能合约]第二节:用EOS开发一个To-do List小应用
- 第14章 任务和特权级保护
- linux下安装配置oracle
- 微课|中学生可以这样学Python(例8.21):选择法排序
- Delphi 的绘图功能[5] - 获取 Canvas 对象
- XQuery的contains函数
- ulipad双击无反应
- Cocos Creator 虚拟摇杆
- echart坐标轴添加下划线问题
- 阿里巴巴产品经理面试主观题
- deepin有线网卡无法连接网络
- Android中屏蔽返回键,HOME键以及模拟HOME键返回效果的方法
- easyui textbox onblur失效
- IE浏览器闪退、自动打开Edge浏览器
热门文章
- 207.课程表(力扣leetcode) 博主可答疑该问题
- css 绝对定位底部居中,css – 在另一个元素的中心下方水平居中绝对定位元素
- android 单手模式开发,单手操作毫无压力 安卓单指缩放技巧
- linux内核类型lagency,使用u盘安装linux(manjaro)时Grub报错
- 简单的数据库group by后要进行某字段拼接
- OAuth2.0认证流程原理
- swagger 参数
- 图解HTTP---------------------------------------------------3
- 微信小程序 this.data与this.setData
- 1347 格子游戏 (并查集)