题目大意: 给一个数 N(1<=N<10^18), 判断它的因子个数是否为4 , 若为4,输出除1之外的三个, 否则输出is not a D_num
由于N很大, 一个个除来找因子时间复杂度太多。因此,用Miller-Rabin算法和pollard_rho 算法求因子个数。直接套用模板, 得到N的所有素因子。然后稍加判断即可。
代码
#include <iostream>
#include <cstdlib>
#include <algorithm>
#include <vector>
using namespace std;
typedef long long ll;
//利用二进制计算a*b%mod
ll multiMod(ll a,ll b,ll mod){
a %= mod , b %= mod;
ll ret = 0;
while(b){
if (b & 1) {
ret += a;
if(ret >= mod) ret -= mod;
}
a <<= 1;
if(a >= mod) a -= mod;
b >>= 1;
}
return ret;
}
//计算a^b%mod
ll powerMod(ll a,ll b,ll mod){
ll ret = 1;
a %= mod;
while(b){
if (b & 1) ret = multiMod(ret , a , mod);
b >>= 1;
a = multiMod(a , a , mod);
}
return ret;
}
//Miller-Rabin测试,测试n是否为素数
bool Miller_Rabin(ll n,int repeat){
if (2 == n || 3 == n) return true;
if (!(n & 1)) return false;
//将n分解为2^s*d
ll d = n - 1;
int s = 0;
while((d&1)== 0) ++s, d>>=1LL;
//srand((unsigned)time(0)); G++不能使用srand(time(NULL)) , 会RE
for(int i = 0; i < repeat; ++i) {//重复repeat次
ll a = rand() % (n - 3) + 2; //取一个随机数,[2,n-1)
ll x = powerMod(a , d , n);
ll y = 0;
for(int j = 0; j < s; ++j){
y = multiMod(x , x , n);
if ( 1 == y && 1 != x && n-1 != x ) return false;
x = y;
}
if ( 1 != y ) return false;
}
return true;
}
ll factor[100000]; //素因子的结果,返回时是无序的
int tol; //素因子的个数
ll gcd(ll a , ll b)
{
ll t;
while(b) {t = a; a = b; b = t%b;}
if(a >= 0) return a;
return -a;
}
ll pollard_rho(ll n , ll c)
{
ll i = 1 , k = 2;
//srand(time(NULL));
ll a = rand() % (n - 1) + 1 , b = a;
while(1)
{
i++;
a = (multiMod(a , a , n) + c) % n;
ll p = gcd(b - a , n);
if(p != 1 && p != n) return p;
if(b == a) return n;
if(i == k) {b = a; k += k;}
}
}
void findfac(ll n , int k)//k为自己设定的值,一般取107
{
if(1 == n) return ;
if(Miller_Rabin(n , 8))
{
factor[tol++] = n;
return ;
}
ll p = n;
int c = k;
while(p >= n) p = pollard_rho(p , c--);
findfac(p , k);
findfac(n/p , k);
}
int main()
{
ll n;
while(cin >> n)
{
tol = 0;
findfac(n , 107);
if(tol != 2 && tol != 3) {cout << "is not a D_num" << endl; continue;}
if(tol == 2) {
if(factor[0] != factor[1]) cout << factor[0] << " " << factor[1] << " " << n << endl;
else cout << "is not a D_num" << endl;
}
else {
if(factor[0] == factor[1] && factor[1] == factor[2])
cout << factor[0] << " " << factor[0] * factor[1] << " " << factor[0] * factor[1] * factor[2] << endl;
else cout << "is not a D_num" << endl;
}
}
}