这一场两个和大数有关的题目,都用到了米勒拉宾算法,有点东西,备忘一下。

题目传送门

F. Divisions

传送门

这个题是求一个数的所有因子个数,但是数据比较大,1e18,所以是大数的题目,正常的求因数的或者求质因数的都过不了,因为这一场的K是米勒拉宾判大素数,先过的K题,所以这个题直接头铁用Miller_Rabin+Pollard_rho这两个东西+因子个数求解公式写过去了。

这两个算法的具体原理不清楚。从别人那里知道了一点。

Miller_Rabin算法的作用是判断一个数是否是个素数,算法速度很快,虽然是概率算法,有一定误判概率,不过可以多次运算大幅度减少误判,误判概率与运算次数t有关,为2^(-t);当t够大时,误判的可能性就很小了。

Pollard_rho算法的作用是求一个数的因子,这个复杂度为O(sqrt(p)),p为这个数的因子。

参考来自别的的博客,传送门:算法集锦(特殊模板集)

因为Miller_Rabin+Pollard_rho这两个东西求出来的是一个数的所有质因数,所以最后要用因数个数求解公式来算出来结果。

关于因数个数求解公式:

对于任何一个自然数N,都可以分解质因子得到如下形式:

那么,N的因子的个数为:

如N=100,分解质因子变形为:100=22∗52,N的因子的个数为:f(N)=f(100)=(1+2)∗(1+2)=9。

即:1,2,4,5,10,20,25,50,100。

特判一下1就可以,找出来素因子之后,我是用map记了一下数然后用因子个数求解公式得到的结果。其他的没什么了。

代码:

  1. #include<iostream>
  2. #include<algorithm>
  3. #include<cstring>
  4. #include<iomanip>
  5. #include<stdio.h>
  6. #include<stdlib.h>
  7. #include<math.h>
  8. #include<cstdlib>
  9. #include<set>
  10. #include<map>
  11. #include<ctime>
  12. #include<stack>
  13. #include<queue>
  14. #include<vector>
  15. #include<set>
  16. using namespace std;
  17. typedef long long ll;
  18. const ll NUM=;//运算次数,Miller_Rabin算法为概率运算,误判率为2^(-NUM);
  19. ll t,f[];
  20. ll mul_mod(ll a,ll b,ll n)//求a*b%n,由于a和b太大,需要用进位乘法
  21. {
  22. a=a%n;
  23. b=b%n;
  24. ll s=;
  25. while(b)
  26. {
  27. if(b&)
  28. s=(s+a)%n;
  29. a=(a<<)%n;
  30. b=b>>;
  31. }
  32. return s;
  33. }
  34. ll pow_mod(ll a,ll b,ll n)//求a^b%n
  35. {
  36. a=a%n;
  37. ll s=;
  38. while(b)
  39. {
  40. if(b&)
  41. s=mul_mod(s,a,n);
  42. a=mul_mod(a,a,n);
  43. b=b>>;
  44. }
  45. return s;
  46. }
  47. bool check(ll a,ll n,ll r,ll s)
  48. {
  49. ll ans=pow_mod(a,r,n);
  50. ll p=ans;
  51. for(ll i=;i<=s;i++)
  52. {
  53. ans=mul_mod(ans,ans,n);
  54. if(ans==&&p!=&&p!=n-)
  55. return true;
  56. p=ans;
  57. }
  58. if(ans!=) return true;
  59. return false;
  60. }
  61. bool Miller_Rabin(ll n)//Miller_Rabin算法,判断n是否为素数
  62. {
  63. if(n<) return false;
  64. if(n==) return true;
  65. if(!(n&)) return false;
  66. ll r=n-,s=;
  67. while(!(r&)){r=r>>;s++;}
  68. for(ll i=;i<NUM;i++)
  69. {
  70. ll a=rand()%(n-)+;
  71. if(check(a,n,r,s))
  72. return false;
  73. }
  74. return true;
  75. }
  76. ll gcd(ll a,ll b)
  77. {
  78. return b==?a:gcd(b,a%b);
  79. }
  80. ll Pollard_rho(ll n,ll c)//Pollard_rho算法,找出n的因子
  81. {
  82. ll i=,j,k=,d,p;
  83. ll x=rand()%n;
  84. ll y=x;
  85. while(true)
  86. {
  87. i++;
  88. x=(mul_mod(x,x,n)+c)%n;
  89. if(y==x) return n;
  90. if(y>x) p=y-x;
  91. else p=x-y;
  92. d=gcd(p,n);
  93. if(d!=&&d!=n) return d;
  94. if(i==k)
  95. {
  96. y=x;
  97. k+=k;
  98. }
  99. }
  100. }
  101. void find(ll n)//找出n的所有因子
  102. {
  103. if(Miller_Rabin(n))
  104. {
  105. f[t++]=n;//保存所有因子
  106. return;
  107. }
  108. ll p=n;
  109. while(p>=n)p=Pollard_rho(p,rand()%(n-)+);//由于p必定为合数,所以通过多次求解必定能求得答案
  110. find(p);
  111. find(n/p);
  112. }
  113. int main()
  114. {
  115. srand(time(NULL));//随机数设定种子
  116. ll n;cin>>n;
  117. if(n==){cout<<""<<endl;return ;}
  118. t=;
  119. find(n);
  120. sort(f,f+t);
  121. map<ll,int>q;
  122. for(int i=;i<t;i++)
  123. {
  124. q[f[i]]++;
  125. }
  126. map<ll,int>::iterator it;
  127. ll ans=;
  128. for(it=q.begin();it!=q.end();it++)
  129. {
  130. int s=it->second;
  131. ans*=+s;
  132. }
  133. cout<<ans<<endl;
  134. return ;
  135. }

计蒜客 18487.Divisions-大数的所有因子个数-Miller_Rabin+Pollard_rho-超快的(大数质因解+因子个数求解公式) (German Collegiate Programming Contest 2015 ACM-ICPC Asia Training League 暑假第一阶段第三场 F)的更多相关文章

  1. 计蒜客 28317.Growling Gears-一元二次方程的顶点公式 (Benelux Algorithm Programming Contest 2014 Final ACM-ICPC Asia Training League 暑假第一阶段第二场 G)

    G. Growling Gears 传送门 此题为签到题,直接中学的数学知识点,一元二次方程的顶点公式(-b/2*a,(4*a*c-b*b)/4*a):直接就可以得到结果. 代码: #include& ...

  2. 计蒜客 28319.Interesting Integers-类似斐波那契数列-递推思维题 (Benelux Algorithm Programming Contest 2014 Final ACM-ICPC Asia Training League 暑假第一阶段第二场 I)

    I. Interesting Integers 传送门 应该是叫思维题吧,反正敲一下脑壳才知道自己哪里写错了.要敢于暴力. 这个题的题意就是给你一个数,让你逆推出递推的最开始的两个数(假设一开始的两个 ...

  3. 计蒜客 18492.Upside down primes-米勒拉宾判大素数 (German Collegiate Programming Contest 2015 ACM-ICPC Asia Training League 暑假第一阶段第三场 K)

    K. Upside down primes 传送门 这个题就是把大数按字符串输进去,判断一下是不是素数,然后反转180度,先判断反转之后的东西是不是一个数,如果是的话,再把这个数判一下是不是素数,如果 ...

  4. 计蒜客 18488.Extreme Sort (German Collegiate Programming Contest 2015 ACM-ICPC Asia Training League 暑假第一阶段第三场 E)

    E.Extreme Sort 传送门 代码: #include<iostream> #include<cstdio> #include<cstring> #incl ...

  5. 计蒜客 28315.Excellent Engineers-线段树(单点更新、区间最值) (Benelux Algorithm Programming Contest 2014 Final ACM-ICPC Asia Training League 暑假第一阶段第二场 E)

    先写这几道题,比赛的时候有事就只签了个到. 题目传送门 E. Excellent Engineers 传送门 这个题的意思就是如果一个人的r1,r2,r3中的某一个比已存在的人中的小,就把这个人添加到 ...

  6. 计蒜客 28206.Runway Planning (BAPC 2014 Preliminary ACM-ICPC Asia Training League 暑假第一阶段第一场 F)

    F. Runway Planning 传送门 题意简直就是有毒,中间bb一堆都是没用的,主要的意思就是度数大于180度的就先减去180度,然后除以10,四舍五入的值就是答案.如果最后结果是0就输出18 ...

  7. 计蒜客 28201.Choosing Ice Cream-gcd (BAPC 2014 Preliminary ACM-ICPC Asia Training League 暑假第一阶段第一场 A)

    开始水一波博客 题目链接: A. Choosing Ice Cream 传送门 题意就是n个冰淇淋,骰子有k个面,问你是否能在公平的概率下转几次骰子能确定买哪个冰淇淋. 举个例子,假设我只有一个冰淇淋 ...

  8. 计蒜客 28202. Failing Components-最短路(Dijkstra) (BAPC 2014 Preliminary ACM-ICPC Asia Training League 暑假第一阶段第一场 B)

    B. Failing Components 传送门 题意就是单向图,从起点开始找最短路,然后统计一下个数就可以.方向是从b到a,权值为s. 直接最短路跑迪杰斯特拉,一开始用数组版的没过,换了一个队列版 ...

  9. German Collegiate Programming Contest 2015 计蒜课

    // Change of Scenery 1 #include <iostream> #include <cstdio> #include <algorithm> ...

随机推荐

  1. Managing WMI security

    TechNet Library TechNet Archive Windows Server 2003 Product Help Windows Server 2003 Product Help Ad ...

  2. android 管理Touch事件

    The onInterceptTouchEvent() method gives a parent the chance to see any touch event before its child ...

  3. 《Cracking the Coding Interview》——第5章:位操作——题目1

    2014-03-19 05:45 题目:给定两个数M和N,将N按照二进制位,覆盖到M的特定段位中去. 解法:位操作,请看代码. 代码: // 5.1 Insert one number into th ...

  4. Windows Phone 图片扩展类

    using System.IO; using System.Text; using System.Net; using System.Threading.Tasks; using System.Win ...

  5. mac安装虚拟机VirtualBox,并在虚拟机上安装centos

    1. 首先从网页上https://www.virtualbox.org/wiki/Downloads下载VirtualBox-6.0.0-127566-OSXdmg文件.我一般把下载的文件放到/opt ...

  6. java 日期处理相关

    /** *获取指定日期 前后指定天数的 日期 * */ public static String getNewDate(String sdate, int days) throws Exception ...

  7. 容器基础(一): Docker介绍

    IaaS IaaS阶段, 用户租借基础设施,但是还是需要像以前管理服务器那样,用脚本或者手工方式在这些机器上部署应用.这个过程中当然难免会碰到云端机器和本地机器环境不一致的问题.想想每一次同步不同机器 ...

  8. linux下的静态库和共享库

    转载&&增加:      我们在编写一个C语言程序的时候,经常会遇到好多重复或常用的部分,如果每次都重新编写固然是可以的,不过那样会大大降低工作效率,并且影响代码的可读性,更不利于后期 ...

  9. hdu1712 分组背包 ACboy needs your help

    ACboy needs your help Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Ot ...

  10. hdu 2141 Can you find it? (二分法)

    Can you find it? Time Limit: 10000/3000 MS (Java/Others)    Memory Limit: 32768/10000 K (Java/Others ...