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

题目传送门

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)的更多相关文章

  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. split array

    public boolean splitArray(int[] nums) { return dividSameSumGroup(0,nums, 0,0); } public boolean divi ...

  2. WPF 利用键盘钩子来捕获键盘,做一些不为人知的事情...完整实例

    键盘钩子是一种可以监控键盘操作的指令. 看到这句话是不是觉得其实键盘钩子可以做很多事情. 场景 当你的程序需要一个全局的快捷键时,可以考虑使用键盘钩子,如大家常用qq的截图快捷键,那么在WPF里怎么去 ...

  3. Linux静态ip设置及一些网络设置

    网络服务配置文件 /etc/sysconfig/network 网络接口配置文件 /etc/sysconfig/network-scripts/ifcfg-INTERFACE_NAME 修改IP永久生 ...

  4. XPS Enable GPIO on EMIO interface 不见了

    按照 <嵌入式系统软硬件协同设计实战指南 -- 基于xilinx Zynq>第九章 zedboard 入门 我一步一步做到9.1.2 (13) 发现 没有  Enable GPOI on ...

  5. Android记事本11

    昨天: Activity的启动模式. 今天: 分析了一些网上的例子的源码. 遇到问题: 无.

  6. 利用nat.123实现SVN外网访问

    背景: 在高效平台的合作中,我们用到了很多团队合作开发的工具,比如SVN.禅道.Confluence等等.有了这些工具,我们可以很好的进行团队合作交流.但同样有所限制,这些工具都是发布在局域网中,只能 ...

  7. token的作用

    token的作用 基于 Token 的身份验证方法 使用基于 Token 的身份验证方法,在服务端不需要存储用户的登录记录.大概的流程是这样的: 客户端使用用户名跟密码请求登录 服务端收到请求,去验证 ...

  8. 基于linux操作系统安装、使用redis详解

    服务端安装 Redis的官方下载站是http://redis.io/download,可以去上面下载最新的安装程序下来,我写此文章时的的稳定版本是2.6.11. 步骤一: 下载Redis 进入软件安装 ...

  9. CSS 3中细线边框如何实现?

    在app应用开发中,我们常常都需要用到css3来设置应用的样式.由于app都是在移动设备上进行展示,所以边框描边的线一般都小于1px,而以往我们使用的都是1px及以上的.那么问题来了,对于小于1px的 ...

  10. MPLAB® XC C编译器的Workstation License的获取及安装方法

    MPLAB®XC C编译器的Workstation License获取及安装方法如下:首先需要购买获得一个XC C编译器的激活码,然后到以下网页(http://www.microchip.com/rl ...