POJ1811 Prime Test大素数判定与因式分解

初探算法与因式分解:从困惑到理解
本文作者分享了自己在学习算法过程中遇到的挑战与成长,特别聚焦于因式分解这一概念的理解过程。从最初的困惑,通过查阅他人代码、阅读算法导论等途径逐渐深入理解,最终发现其原理并不如想象中复杂。文章重点阐述了算法导论对于解决因式分解问题的帮助,以及二分法思想在实际应用中的体现。

说实在的,这题当初完全不懂。上网查了别人的AC代码,感觉也没看懂。后来,一怒之下,把算法导论买了。。。看完相关知识后,才发觉,没有想象中的复杂。。

但话又说回来,其实因式分解这一块还是比较难的。但在这题,只要求最小素因子,所以比较简单。其思想是一种二分。

#include<stdio.h>
#include<string.h>
#include<time.h>
#include<stdlib.h>
#define s 30//随机测试数
typedef long long ll;
ll min;
ll multi(ll a,ll b,ll m){
	ll ans=0;
	while(a){
		if(a&1){
			ans=(ans+b)%m;
			a>>=1;
			b=b*2%m;
		}
		else{
			a>>=1;
			b=b*2%m;
		}
	}
	return ans;
}
ll pow(ll a,ll b,ll m){
	ll ans=1;
	ll x=a;
	while(b){
		if(b&1){
			ans=multi(ans,x,m);
			x=multi(x,x,m);
			b>>=1;
		}
		else{
			x=multi(x,x,m);
			b>>=1;
		}
	}
	return ans;
}
bool check(ll n){
	ll a=rand()%(n-1)+1;
	int t=0;
	ll r=n-1;
	while(!(r%2)){
		r>>=1;
		t++;
	}
	ll x=pow(a,r,n);	
	for(int i=1;i<=t;i++){
		ll y=multi(x,x,n);
		if(y==1&&x!=1&&x!=n-1)
			return 0;
		x=y;
	}
	if(x!=1)
		return 0;
	return 1;
}
bool prime(ll n){
	if(n==2)return 1;
	if(n%2==0)return 0;
	for(int i=1;i<=s;i++)
		if(!check(n))
			return 0;
	return 1;
}
ll gcd(ll a,ll b){
	return b==0?a:gcd(b,a%b);
}
ll rho(ll n,int c){
	ll x=rand()%(n-1);
	ll y=x,d;
	int k=2,i=1;
	while(1){
		i++;
		x=(multi(x,x,n)+c)%n;
		d=gcd(y-x,n);
		if(d>1&&d<n)
			return d;
		if(x==y)
			return n;
		if(i==k){
			y=x;
			k<<=1;
		}
	}
}
void find(ll n,int c){
	if(n==1)return;
	ll p=n;
	if(prime(n)){	
		if(min>n)min=n;
	}
	else{
		while(p>=n)
			p=rho(n,c--);	
		find(n/p,c);
		find(p,c);
	}
}
int main(){
	freopen("t.txt","r",stdin);
	int T;
	scanf("%d",&T);
	while(T--){
		ll n;
		scanf("%lld",&n);
		if(prime(n))
			printf("Prime\n");
		else {
			min=n;
			int c=10452;//随机测试数
			find(n,c);
			printf("%lld\n",min);
		}
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值