计蒜客 18487.Divisions-大数的所有因子个数-Miller_Rabin+Pollard_rho-超快的(大数质因解+因子个数求解公式) (German Collegiate Programming Contest 2015 ACM-ICPC Asia Training League 暑假第一阶段第三场 F)
这一场两个和大数有关的题目,都用到了米勒拉宾算法,有点东西,备忘一下。
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记了一下数然后用因子个数求解公式得到的结果。其他的没什么了。
代码:
- #include<iostream>
- #include<algorithm>
- #include<cstring>
- #include<iomanip>
- #include<stdio.h>
- #include<stdlib.h>
- #include<math.h>
- #include<cstdlib>
- #include<set>
- #include<map>
- #include<ctime>
- #include<stack>
- #include<queue>
- #include<vector>
- #include<set>
- using namespace std;
- typedef long long ll;
- const ll NUM=;//运算次数,Miller_Rabin算法为概率运算,误判率为2^(-NUM);
- ll t,f[];
- ll mul_mod(ll a,ll b,ll n)//求a*b%n,由于a和b太大,需要用进位乘法
- {
- a=a%n;
- b=b%n;
- ll s=;
- while(b)
- {
- if(b&)
- s=(s+a)%n;
- a=(a<<)%n;
- b=b>>;
- }
- return s;
- }
- ll pow_mod(ll a,ll b,ll n)//求a^b%n
- {
- a=a%n;
- ll s=;
- while(b)
- {
- if(b&)
- s=mul_mod(s,a,n);
- a=mul_mod(a,a,n);
- b=b>>;
- }
- return s;
- }
- bool check(ll a,ll n,ll r,ll s)
- {
- ll ans=pow_mod(a,r,n);
- ll p=ans;
- for(ll i=;i<=s;i++)
- {
- ans=mul_mod(ans,ans,n);
- if(ans==&&p!=&&p!=n-)
- return true;
- p=ans;
- }
- if(ans!=) return true;
- return false;
- }
- bool Miller_Rabin(ll n)//Miller_Rabin算法,判断n是否为素数
- {
- if(n<) return false;
- if(n==) return true;
- if(!(n&)) return false;
- ll r=n-,s=;
- while(!(r&)){r=r>>;s++;}
- for(ll i=;i<NUM;i++)
- {
- ll a=rand()%(n-)+;
- if(check(a,n,r,s))
- return false;
- }
- return true;
- }
- ll gcd(ll a,ll b)
- {
- return b==?a:gcd(b,a%b);
- }
- ll Pollard_rho(ll n,ll c)//Pollard_rho算法,找出n的因子
- {
- ll i=,j,k=,d,p;
- ll x=rand()%n;
- ll y=x;
- while(true)
- {
- i++;
- x=(mul_mod(x,x,n)+c)%n;
- if(y==x) return n;
- if(y>x) p=y-x;
- else p=x-y;
- d=gcd(p,n);
- if(d!=&&d!=n) return d;
- if(i==k)
- {
- y=x;
- k+=k;
- }
- }
- }
- void find(ll n)//找出n的所有因子
- {
- if(Miller_Rabin(n))
- {
- f[t++]=n;//保存所有因子
- return;
- }
- ll p=n;
- while(p>=n)p=Pollard_rho(p,rand()%(n-)+);//由于p必定为合数,所以通过多次求解必定能求得答案
- find(p);
- find(n/p);
- }
- int main()
- {
- srand(time(NULL));//随机数设定种子
- ll n;cin>>n;
- if(n==){cout<<""<<endl;return ;}
- t=;
- find(n);
- sort(f,f+t);
- map<ll,int>q;
- for(int i=;i<t;i++)
- {
- q[f[i]]++;
- }
- map<ll,int>::iterator it;
- ll ans=;
- for(it=q.begin();it!=q.end();it++)
- {
- int s=it->second;
- ans*=+s;
- }
- cout<<ans<<endl;
- return ;
- }
计蒜客 18487.Divisions-大数的所有因子个数-Miller_Rabin+Pollard_rho-超快的(大数质因解+因子个数求解公式) (German Collegiate Programming Contest 2015 ACM-ICPC Asia Training League 暑假第一阶段第三场 F)的更多相关文章
- 计蒜客 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& ...
- 计蒜客 28319.Interesting Integers-类似斐波那契数列-递推思维题 (Benelux Algorithm Programming Contest 2014 Final ACM-ICPC Asia Training League 暑假第一阶段第二场 I)
I. Interesting Integers 传送门 应该是叫思维题吧,反正敲一下脑壳才知道自己哪里写错了.要敢于暴力. 这个题的题意就是给你一个数,让你逆推出递推的最开始的两个数(假设一开始的两个 ...
- 计蒜客 18492.Upside down primes-米勒拉宾判大素数 (German Collegiate Programming Contest 2015 ACM-ICPC Asia Training League 暑假第一阶段第三场 K)
K. Upside down primes 传送门 这个题就是把大数按字符串输进去,判断一下是不是素数,然后反转180度,先判断反转之后的东西是不是一个数,如果是的话,再把这个数判一下是不是素数,如果 ...
- 计蒜客 18488.Extreme Sort (German Collegiate Programming Contest 2015 ACM-ICPC Asia Training League 暑假第一阶段第三场 E)
E.Extreme Sort 传送门 代码: #include<iostream> #include<cstdio> #include<cstring> #incl ...
- 计蒜客 28315.Excellent Engineers-线段树(单点更新、区间最值) (Benelux Algorithm Programming Contest 2014 Final ACM-ICPC Asia Training League 暑假第一阶段第二场 E)
先写这几道题,比赛的时候有事就只签了个到. 题目传送门 E. Excellent Engineers 传送门 这个题的意思就是如果一个人的r1,r2,r3中的某一个比已存在的人中的小,就把这个人添加到 ...
- 计蒜客 28206.Runway Planning (BAPC 2014 Preliminary ACM-ICPC Asia Training League 暑假第一阶段第一场 F)
F. Runway Planning 传送门 题意简直就是有毒,中间bb一堆都是没用的,主要的意思就是度数大于180度的就先减去180度,然后除以10,四舍五入的值就是答案.如果最后结果是0就输出18 ...
- 计蒜客 28201.Choosing Ice Cream-gcd (BAPC 2014 Preliminary ACM-ICPC Asia Training League 暑假第一阶段第一场 A)
开始水一波博客 题目链接: A. Choosing Ice Cream 传送门 题意就是n个冰淇淋,骰子有k个面,问你是否能在公平的概率下转几次骰子能确定买哪个冰淇淋. 举个例子,假设我只有一个冰淇淋 ...
- 计蒜客 28202. Failing Components-最短路(Dijkstra) (BAPC 2014 Preliminary ACM-ICPC Asia Training League 暑假第一阶段第一场 B)
B. Failing Components 传送门 题意就是单向图,从起点开始找最短路,然后统计一下个数就可以.方向是从b到a,权值为s. 直接最短路跑迪杰斯特拉,一开始用数组版的没过,换了一个队列版 ...
- German Collegiate Programming Contest 2015 计蒜课
// Change of Scenery 1 #include <iostream> #include <cstdio> #include <algorithm> ...
随机推荐
- Managing WMI security
TechNet Library TechNet Archive Windows Server 2003 Product Help Windows Server 2003 Product Help Ad ...
- android 管理Touch事件
The onInterceptTouchEvent() method gives a parent the chance to see any touch event before its child ...
- 《Cracking the Coding Interview》——第5章:位操作——题目1
2014-03-19 05:45 题目:给定两个数M和N,将N按照二进制位,覆盖到M的特定段位中去. 解法:位操作,请看代码. 代码: // 5.1 Insert one number into th ...
- Windows Phone 图片扩展类
using System.IO; using System.Text; using System.Net; using System.Threading.Tasks; using System.Win ...
- mac安装虚拟机VirtualBox,并在虚拟机上安装centos
1. 首先从网页上https://www.virtualbox.org/wiki/Downloads下载VirtualBox-6.0.0-127566-OSXdmg文件.我一般把下载的文件放到/opt ...
- java 日期处理相关
/** *获取指定日期 前后指定天数的 日期 * */ public static String getNewDate(String sdate, int days) throws Exception ...
- 容器基础(一): Docker介绍
IaaS IaaS阶段, 用户租借基础设施,但是还是需要像以前管理服务器那样,用脚本或者手工方式在这些机器上部署应用.这个过程中当然难免会碰到云端机器和本地机器环境不一致的问题.想想每一次同步不同机器 ...
- linux下的静态库和共享库
转载&&增加: 我们在编写一个C语言程序的时候,经常会遇到好多重复或常用的部分,如果每次都重新编写固然是可以的,不过那样会大大降低工作效率,并且影响代码的可读性,更不利于后期 ...
- hdu1712 分组背包 ACboy needs your help
ACboy needs your help Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Ot ...
- hdu 2141 Can you find it? (二分法)
Can you find it? Time Limit: 10000/3000 MS (Java/Others) Memory Limit: 32768/10000 K (Java/Others ...