HDU 4344

其实不过是大整数分解。。。

注意两点:注意L 不能==N

但是,N却可以是素数。。。囧

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstdio>
#define LL __int64
#define MAX 1LL<<61
#define Times 8
#define N 501
#define C 101
using namespace std;
LL cop[N];
int ct;

bool cmp(LL a,LL b){
	if(a<b) return true;
	return false;
}

LL gcd(LL a,LL b){
	return b==0?a:gcd(b,a%b);
}

LL random(LL n){
	return (LL)((double)rand()/RAND_MAX*n+0.5);
}

LL multi(LL a,LL b,LL m){   //a*b%m
	LL ret=0;
	while(b){
		if(b&1)
		ret=(ret+a)%m;
		b>>=1;
		a=(a<<1)%m;
	}
	return ret;
}

LL quick(LL a,LL b,LL m){
	LL ans=1;
	a%=m;
	while(b){
		if(b&1){
			ans=multi(ans,a,m);
			b--;
		}
		b/=2;
		a=multi(a,a,m);
	}
	return ans;
}

bool Witness(LL a,LL n){
	LL m=n-1;
	int j=0;
	while(!(m&1)){
		j++;
		m>>=1;
	}
	LL x=quick(a,m,n);
	if(x==1||x==n-1)
	return false;
	while(j--){
		x=multi(x,x,n);
		if(x==n-1)
		return false;
	}
	return true;
}

bool Miller_Rabin(LL n){
	if(n<2) return false;
	if(n==2) return true;
	if(!(n&1)) return false;
	for(int i=1;i<=Times;i++){
		LL a=random(n-2)+1;
		if(Witness(a,n)) return false;
	}
	return true;
}

LL Pollard_Rho(LL n,int c){
	LL x,y,d,i=1,k=2;
	x=random(n-1)+1;
	y=x;
	while(true){
		i++;
		x=(multi(x,x,n)+c)%n;
		d=gcd(y-x,n);
		if(d>1&&d<n){
			return d;
		}
		if(y==x) return n;
		if(i==k){
			y=x;
			k=k<<1;
		}
	}
}

void find(LL n,int k){
	if(n==1) return ;
	if(Miller_Rabin(n)){
		cop[++ct]=n;
		return ;
	}
	LL p=n;
	while(p>=n)
	p=Pollard_Rho(p,k--);
	find(p,k);
	find(n/p,k);
}

int main(){
	int T;
	LL n;
	scanf("%d",&T);
	while(T--){
		scanf("%I64d",&n);
		ct=0;
		find(n,C);
		sort(cop+1,cop+1+ct,cmp);
		if(ct==1){
			printf("1 1\n");
			continue;
		}
		LL cnt=0;LL tmp=0; LL ans=0;
		cop[0]=1;
		cop[++ct]=1;
		for(int i=1;i<=ct;i++){
			if(cop[i]!=cop[i-1]){
				ans+=tmp;
				tmp=cop[i];
				cnt++;
			}
			else{
				tmp*=cop[i];
			}
		}
		if(ans==n)
		ans/=cop[1];
		printf("%I64d %I64d\n",cnt-1,ans);
	}
	return 0;
}

  

时间: 2024-11-08 20:07:50

HDU 4344的相关文章

HDU 4344 随机法判素数(费马小定理

#include <cstdio> #include <ctime> #include <cmath> #include <algorithm> using namespace std; typedef long long ll; const int N = 108; const int S = 10; ll mult_mod(ll a, ll b, ll c) { a %= c; b %= c; ll ret = 0; while(b) { if(b&am

HDU 4344 大数分解大素数判定

这里贴个模板吧.反正是不太理解 看原题就可以理解用法!! #include <cstdio> #include <iostream> #include <algorithm> #include <cmath> #include <cstring> #include <map> using namespace std; #define Times 10 typedef __int64 LL; map<LL,int>m; LL

[HDU 4344]Mark the Rope(Pollard_rho+Miller_Rabin)

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 used2. He will choose a length L (N>L>1) and he defines the mark’s va

pollard_rho 学习总结 Miller_Rabbin 复习总结

吐槽一下名字,泼辣的肉..OwO 我们知道分解出一个整数的所有质因子是O(sqrt(n)/ln(n))的 但是当n=10^18的时候就显得非常无力的 这个算法可以在大概O(n^(1/4))的时间复杂度的情况下把n分解成p*q 递归分解就可以得到质因子了,跑得非常快 做法是这样的,考虑利用生日悖论 设范围为[1,365]的正整数 设集合{x1,x2……,xk}当k大概到58时 那么这个集合中存在两个数相等的概率几乎为99% 那么相应的对于一个数n,我们随机一个集合,这个集合中任取两个数x,y,gc

HDU 6203 ping ping ping [LCA,贪心,DFS序,BIT(树状数组)]

题目链接:[http://acm.hdu.edu.cn/showproblem.php?pid=6203] 题意 :给出一棵树,如果(a,b)路径上有坏点,那么(a,b)之间不联通,给出一些不联通的点对,然后判断最少有多少个坏点. 题解 :求每个点对的LCA,然后根据LCA的深度排序.从LCA最深的点对开始,如果a或者b点已经有点被标记了,那么continue,否者标记(a,b)LCA的子树每个顶点加1. #include<Bits/stdc++.h> using namespace std;

HDU 5542 The Battle of Chibi dp+树状数组

题目:http://acm.hdu.edu.cn/showproblem.php?pid=5542 题意:给你n个数,求其中上升子序列长度为m的个数 可以考虑用dp[i][j]表示以a[i]结尾的长度为j的上升子序列有多少 裸的dp是o(n2m) 所以需要优化 我们可以发现dp的第3维是找比它小的数,那么就可以用树状数组来找 这样就可以降低复杂度 #include<iostream> #include<cstdio> #include<cstring> #include

hdu 1207 汉诺塔II (DP+递推)

汉诺塔II Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 4529    Accepted Submission(s): 2231 Problem Description 经典的汉诺塔问题经常作为一个递归的经典例题存在.可能有人并不知道汉诺塔问题的典故.汉诺塔来源于印度传说的一个故事,上帝创造世界时作了三根金刚石柱子,在一根柱子上从下往

[hdu 2102]bfs+注意INF

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2102 感觉这个题非常水,结果一直WA,最后发现居然是0x3f3f3f3f不够大导致的--把INF改成INF+INF就过了. #include<bits/stdc++.h> using namespace std; bool vis[2][15][15]; char s[2][15][15]; const int INF=0x3f3f3f3f; const int fx[]={0,0,1,-1};

HDU 3555 Bomb (数位DP)

数位dp,主要用来解决统计满足某类特殊关系或有某些特点的区间内的数的个数,它是按位来进行计数统计的,可以保存子状态,速度较快.数位dp做多了后,套路基本上都差不多,关键把要保存的状态给抽象出来,保存下来. 简介: 顾名思义,所谓的数位DP就是按照数字的个,十,百,千--位数进行的DP.数位DP的题目有着非常明显的性质: 询问[l,r]的区间内,有多少的数字满足某个性质 做法根据前缀和的思想,求出[0,l-1]和[0,r]中满足性质的数的个数,然后相减即可. 算法核心: 关于数位DP,貌似写法还是