【CODECHEF】【phollard rho + miller_rabin】The First Cube
All submissions for this problem are available.
Read problems statements in Mandarin Chinese and Russian.
This problem's statement is really a short one.
You are given an integer S. Consider an infinite sequence S, 2S, 3S, ... . Find the first number in this sequence that can be represented as Q3, where Q is some positive integer number. As the sought number could be very large, please print modulo (109 + 7).
The number S will be given to you as a product of N positive integer numbers A1, A2, ..., AN, namely S = A1 * A2 * ... * AN
Input
The first line of the input contains an integer T denoting the number of test cases. The description of T test cases follows.
The first line of each test case contains an integer N.
Then there is a line, containing N space separated integers, denoting the numbers A1, A2, ..., AN.
Output
For each test case, output a single line containing the first term of the sequence which is the perfect cube, modulo 109+7.
Constraints
- 1 ≤ T ≤ 10
- (Subtask 1): N = 1, 1 ≤ S ≤ 109 - 15 points.
- (Subtask 2): N = 1, 1 ≤ S ≤ 1018 - 31 point.
- (Subtask 3): 1 ≤ N ≤ 100, 1 ≤ Ai ≤ 1018 - 54 points.
Example
Input: 2 2 2 2 2 2 3 Output: 8 216
Explanation
Example case 1. First few numbers in the infinite sequence 4, 8, 12, 16, 20, , etc. In this sequence, 8 is the first number which is also a cube (as 23 = 8).
Example case 2. First few numbers in the infinite sequence 6, 12, 18, 24, , etc. In this sequence, 216 is the first number which is also a cube (as 63 = 216).
【分析】
挺模板的东西,就当复习一下了。
1 /* 2 宋代李冠 3 《蝶恋花·春暮》 4 遥夜亭皋闲信步。 5 才过清明,渐觉伤春暮。 6 数点雨声风约住。朦胧淡月云来去。 7 桃杏依稀香暗渡。 8 谁在秋千,笑里轻轻语。 9 一寸相思千万绪。人间没个安排处。 10 */ 11 #include <cstdio> 12 #include <cstring> 13 #include <algorithm> 14 #include <cmath> 15 #include <queue> 16 #include <vector> 17 #include <iostream> 18 #include <string> 19 #include <ctime> 20 #include <map> 21 #define LOCAL 22 const int MAXN = 105 + 10; 23 const long long MOD = 1000000007; 24 const double Pi = acos(-1.0); 25 long long G = 15;//原根 26 const int MAXM = 60 * 2 + 10; 27 using namespace std; 28 typedef long long ll; 29 ll read(){ 30 ll flag = 1, x = 0; 31 char ch; 32 ch = getchar(); 33 while (ch < '1' || ch > '9') {if (ch == '-') flag = -1; ch = getchar();} 34 while (ch >= '0' && ch <= '9') {x = x * 10 + (ch - '0'); ch = getchar();} 35 return x * flag; 36 } 37 map<ll, int>Num;//记录个数 38 ll data[MAXN]; 39 ll n; 40 41 ll mul(ll a, ll b, ll c){//又要用快速乘QAQ 42 if (b == 0) return 0ll; 43 if (b == 1) return a % c; 44 ll tmp = mul(a, b / 2, c); 45 if (b % 2 == 0) return (tmp + tmp) % c; 46 else return (((tmp + tmp) % c) + (a % c)) % c; 47 } 48 ll pow(ll a, ll b, ll c){ 49 if (b == 0) return 1ll; 50 if (b == 1) return a % c; 51 ll tmp = pow(a, b / 2, c); 52 if (b % 2 == 0) return mul(tmp, tmp, c); 53 else return mul(mul(tmp, tmp, c), a, c); 54 } 55 bool Sec_check(ll a, ll b, ll c){ 56 ll tmp = pow(a, b, c); 57 if (tmp != 1 && tmp != (c - 1)) return 0; 58 if (tmp == (c - 1) || (b % 2 != 0)) return 1; 59 return Sec_check(a, b / 2, c); 60 } 61 //判断n是否是素数 62 bool miller_rabin(ll n){ 63 int cnt = 20; 64 while (cnt--){ 65 ll a = (ll)rand() % (n - 1) + 1; 66 if (!Sec_check(a, n - 1, n)) return 0; 67 } 68 return 1; 69 } 70 ll gcd(ll a, ll b){return b == 0ll ? a : gcd(b, a % b);} 71 ll pollard_rho(ll a, ll c){ 72 ll i = 1, k = 2; 73 ll x, y, d; 74 x = (ll)((double)(rand() / RAND_MAX) * (a - 2) + 0.5) + 1ll; 75 y = x; 76 while (1){ 77 i++; 78 x = (mul(x, x, a) % a + c) % a; 79 d = gcd(y - x + a, a); 80 if (d > 1 && d < a) return d; 81 if (y == x) return a;//失败 82 if (i == k){ 83 k <<= 1; 84 y = x; 85 } 86 } 87 } 88 void find(ll a, ll c){ 89 if (a == 1) return; 90 if (miller_rabin(a)){ 91 Num[a]++; 92 return; 93 } 94 ll p = a; 95 while (p >= a) pollard_rho(a, c--); 96 pollard_rho(p, c); 97 pollard_rho(a / p, c); 98 } 99 void init(){ 100 Num.clear(); 101 scanf("%d", &n); 102 for (int i = 1; i <= n; i++) { 103 data[i] = read(); 104 find(data[i], 15000); 105 } 106 } 107 void work(){ 108 ll Ans = 1; 109 for (int i = 1; i <= n; i++) Ans = (Ans * data[i]) % MOD; 110 for (map<ll, int>::iterator it = Num.begin(); it != Num.end(); it++){ 111 it->second %= 3; 112 if (it->second){ 113 for (int i = it->second; i < 3; i++) Ans = (Ans * ((it->first) % MOD)) % MOD; 114 } 115 } 116 printf("%lld\n", Ans); 117 } 118 119 int main(){ 120 int T; 121 122 scanf("%d", &T); 123 while (T--){ 124 init(); 125 work(); 126 } 127 return 0; 128 }