hdu 4344 Mark the Rope (Miller Rabbin + Pollard rho)

Mark the Rope

Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 2764    Accepted Submission(s): 916


Problem Description
Eric has a long rope whose length is N, now he wants to mark on the rope with different colors. The way he marks the rope is:
1. He will choose a color that hasn’t been used
2. He will choose a length L (N>L>1) and he defines the mark’s value equals L
3. From the head of the rope, after every L length, he marks on the rope (you can assume the mark’s length is 0 )
4. When he chooses the length L in step 2, he has made sure that if he marks with this length, the last mark will be at the tail of the rope
Eric is a curious boy, he want to choose K kinds of marks. Every two of the marks’ value are coprime(gcd(l1,l2)=1). Now Eric wants to know the max K. After he chooses the max K kinds of marks, he wants to know the max sum of these K kinds of marks’ values.
You can assume that Eric always can find at least one kind of length to mark on the rope.
 

Input
First line: a positive number T (T<=500) representing the number of test cases
2 to T+1 lines: every line has only a positive number N (N<2 63) representing the length of rope
 

Output
For every test case, you only need to output K and S separated with a space
 

Sample Input
  
  
2 180 198
 

Sample Output
  
  
3 18 3 22
 

Author
HIT
 

Source
 

Recommend
zhuyuanchen520   |   We have carefully selected several similar problems for you:   4348  4347  4346  4345  4343 


题解:Miller Rabbin + Pollard rho

Miller Rabbin 可以在O(s(logn)^3)的时间复杂度内判断一个数是否为素数,有2^(-s)的概率出错

Pollard rho 是基于Miller Rabbin的一种快速分解质因数的做法。

该算法的大致流程是先判断当前数是否为素数(用Miller Rabbin),如果是直接记录下该质数,直接返回。如果不是就试图找到一个因子(可以不是质因子),然后对于当前因子p,和n/p分别递归寻找质因子。

对于质因数的寻找,我们采用一种随机化的算法。我们假设要找到的质因子为p,先随机取一个x,然后用x构造y,使p=gcd(x-y,n)如果p不等于1那么就找到了一个质因子,如果找不到我们就不断的调整x,使x=x*x+c(c一般可以随机),直到x==y出现循环,则选取失败。重新选取x,重复上述过程。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define LL long long 
#define N 10000003
using namespace std;
LL n,mx,cnt,num[N],prime[N],c[N];
LL mul(LL a,LL b,LL p)
{
	LL ans=0; LL base=a%p;
	while (b) {
		if (b&1) ans=(ans+base)%p;
		b>>=1;
		base=(base+base)%p;
	}
	return ans;
}
LL quickpow(LL num,LL x,LL p)
{
	LL ans=1; LL base=num%p;
	while (x) {
		if (x&1) ans=mul(ans,base,p);
		x>>=1;
		base=mul(base,base,p);
	}
	return ans;
}
bool miller_rabbin(LL n)
{
	if (n==2) return true;
	if (!(n&1)) return false;
	LL t=0,a,x,y,u=n-1;
	while (!(u&1)) t++,u>>=1;
	for (int i=0;i<=10;i++) {
		a=rand()*rand()%(n-1)+1;
		x=quickpow(a,u,n);
		for (int j=0;j<t;j++) {
			y=mul(x,x,n);
			if (y==1&&x!=1&&x!=n-1) return false;
			x=y;
		}
		if (x!=1) return false;
	}
	return true;
}
LL gcd(LL x,LL y)
{
	LL r;
	while (y) {
		r=x%y;
		x=y; y=r;
	}
	return x;
}
LL pollard_rho(LL n,LL c)
{
	LL i=1,k=2;
	LL x=rand()%(n-1)+1,y=x,p=1;
	while (p==1) {
		i++;
		x=(mul(x,x,n)+c)%n;
		p=gcd((y-x+n)%n,n);
		if (y==x) return n;
		if (i==k) y=x,k<<=1;
	}
	return p;
}
void solve(LL n)
{
	if (n==1) return;
	if (miller_rabbin(n)) {
		num[++cnt]=n;
		return;
	}
	LL p=n;  
	while (p==n) p=pollard_rho(p,rand()%(n-1)+1);
	solve(p); solve(n/p);
}
int main()
{
	freopen("a.in","r",stdin);
	freopen("my.out","w",stdout);
	srand(2000001001);
	int T; scanf("%d",&T);
	while (T--) {
		scanf("%I64d",&n);
		//cout<<n<<endl;
		mx=0; cnt=0;
		solve(n); int k=0;
		sort(num+1,num+cnt+1);
		prime[++k]=num[1]; c[k]=1;
		for (int i=2;i<=cnt;i++) 
		 if (num[i]==num[i-1]) prime[k]*=num[i];
		 else prime[++k]=num[i];
		printf("%d ",k);
		LL sum=0;
		for (int i=1;i<=k;i++) sum+=prime[i];
		if (k==1) sum/=num[1];
		printf("%I64d\n",sum);
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值