#include <iostream>
#include <algorithm>
#include <vector>
#include <cassert>
using namespace std ;
typedef long long LL ;
typedef pair<int,int> PII ;
typedef vector<int> VI ;
const int INF = 1e9+100 ;
const LL INFLL = (LL)INF*INF ;
#define REP(i,n) for(int i=0;i<(n);++i)
#define ALL(c) c.begin(),c.end()
#define FOREACH(i,c) for(auto i=(c).begin();i!=(c).end();++i)
#define CLEAR(t) memset(t,0,sizeof(t))
#define PB push_back
#define MP make_pair
#define FI first
#define SE second
template<class T> void maxi(T &a, const T &b) { a = max(a,b) ; }
template<class T1,class T2> ostream& operator<<(ostream &s, const pair<T1,T2> &x) { return s << "(" << x.FI << "," << x.SE << ")" ;}
template<class T> ostream& operator<<(ostream &s, const vector<T> &t) { FOREACH(it, t) s << *it << " " ; return s ; }
template<class T> void _debug(bool printName, const char* s, const T &x) { if(printName) cerr << s << "=" ; cerr << x << endl ; }
void _debug(bool, const char* s, const char*) {
for(;*s;s++) if(*s!='"') { cerr << *s ; } cerr << endl ;
}
template<class T, class... R> void _debug(bool printName, const char* s, const T &x, R... y) {
bool o=0, str=(*s=='"') ;
for(; o || *s!=',' ; s++) if(*s=='"') o=!o ; else if(printName||str) cerr<<*s ;
for(s++;*s && *s==' '; s++) ;
if(!str) { if(printName) cerr << "=" ; cerr << x ; if(*s!='"' && printName) cerr << "," ; } cerr << " " ;
_debug(printName, s, y...) ;
}
template<class T> void _coord(const T &x) { cerr << "[" << x << "]" ; }
template<class T, class... R> void _coord(const T &x, R... y) { cerr << "[" << x << "]" ; _coord(y...) ; }
template<class T, class I> void _val(T &t, const I &i) { cerr << t[i] ; }
template<class T, class I, class... J> void _val(T &t, const I &i, J... j) { _val(t[i], j...) ; }
#ifndef LOCAL
#define CERR(...)
#define DEBUG(...)
#define DARRAY(...)
#else
#define CERR(...) if(DFLAG) _debug(0, #__VA_ARGS__, __VA_ARGS__)
#define DEBUG(...) if(DFLAG) _debug(1, #__VA_ARGS__, __VA_ARGS__)
#define DARRAY(t,...) if(DFLAG) { cerr << #t ; _coord(__VA_ARGS__) ; cerr << " = " ; _val(t,__VA_ARGS__) ; cerr << endl ; }
#define DFLAG 0
#endif
////////////////////////////////////////////////////////////////////////////////
const int LIMIT=0.85e6 ;
LL t[LIMIT] ;
int len=0 ;
LL N, ret=1 ;
VI primes ;
void doit(LL n, int i, bool isNew, LL* it) {
if(isNew) {
assert(1<=n && n<=N) ;
it = lower_bound(it, t+len, N/n, greater<LL>()) ;
maxi(ret, n*(*it)) ;
}
int p=primes[i] ;
if(((double)p)*n<=N) doit(n*p, i, true, it) ;
if(i+1<primes.size())
doit(n, i+1, false, it) ;
}
// MEET IN THE MIDDLE po zbiorach liczb pierwszych
int main()
{
ios_base::sync_with_stdio(0) ;
int k, p ;
cin >> k >> N ;
primes.resize(k) ;
REP(i, k)
cin >> primes[i] ;
sort(ALL(primes)) ;
DEBUG(primes) ;
// Krok1: tablicuje liczby generowane przez najmniejsze liczby pierwsze
t[0]=1 ; len=1 ;
VI unused ;
for(int p: primes) {
int next=len ;
LL M=N/p ;
bool ok=true ;
for(int i=0 ; i<len && ok ; i++) {
for(LL a=t[i] ; a<=M && ok ; a*=p) {
if(next<LIMIT)
t[next++] = a*p ;
else
ok=false ;
}
}
if(ok) {
DEBUG("biore ", p) ;
len=next ;
}
else {
unused.PB(p) ;
}
}
primes=unused ;
DEBUG("zostaly:", primes) ;
sort(t,t+len) ;
reverse(t,t+len) ;
//DEBUG(vector<LL>(t,t+len)) ;
DEBUG(len) ;
reverse(ALL(primes)) ;
// Krok2: generuje rekrencyjnie liczby z pozostalych liczb pierwszych
doit(1, 0, true, t) ;
cout << ret << endl ;
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 | #include <iostream> #include <algorithm> #include <vector> #include <cassert> using namespace std ; typedef long long LL ; typedef pair<int,int> PII ; typedef vector<int> VI ; const int INF = 1e9+100 ; const LL INFLL = (LL)INF*INF ; #define REP(i,n) for(int i=0;i<(n);++i) #define ALL(c) c.begin(),c.end() #define FOREACH(i,c) for(auto i=(c).begin();i!=(c).end();++i) #define CLEAR(t) memset(t,0,sizeof(t)) #define PB push_back #define MP make_pair #define FI first #define SE second template<class T> void maxi(T &a, const T &b) { a = max(a,b) ; } template<class T1,class T2> ostream& operator<<(ostream &s, const pair<T1,T2> &x) { return s << "(" << x.FI << "," << x.SE << ")" ;} template<class T> ostream& operator<<(ostream &s, const vector<T> &t) { FOREACH(it, t) s << *it << " " ; return s ; } template<class T> void _debug(bool printName, const char* s, const T &x) { if(printName) cerr << s << "=" ; cerr << x << endl ; } void _debug(bool, const char* s, const char*) { for(;*s;s++) if(*s!='"') { cerr << *s ; } cerr << endl ; } template<class T, class... R> void _debug(bool printName, const char* s, const T &x, R... y) { bool o=0, str=(*s=='"') ; for(; o || *s!=',' ; s++) if(*s=='"') o=!o ; else if(printName||str) cerr<<*s ; for(s++;*s && *s==' '; s++) ; if(!str) { if(printName) cerr << "=" ; cerr << x ; if(*s!='"' && printName) cerr << "," ; } cerr << " " ; _debug(printName, s, y...) ; } template<class T> void _coord(const T &x) { cerr << "[" << x << "]" ; } template<class T, class... R> void _coord(const T &x, R... y) { cerr << "[" << x << "]" ; _coord(y...) ; } template<class T, class I> void _val(T &t, const I &i) { cerr << t[i] ; } template<class T, class I, class... J> void _val(T &t, const I &i, J... j) { _val(t[i], j...) ; } #ifndef LOCAL #define CERR(...) #define DEBUG(...) #define DARRAY(...) #else #define CERR(...) if(DFLAG) _debug(0, #__VA_ARGS__, __VA_ARGS__) #define DEBUG(...) if(DFLAG) _debug(1, #__VA_ARGS__, __VA_ARGS__) #define DARRAY(t,...) if(DFLAG) { cerr << #t ; _coord(__VA_ARGS__) ; cerr << " = " ; _val(t,__VA_ARGS__) ; cerr << endl ; } #define DFLAG 0 #endif //////////////////////////////////////////////////////////////////////////////// const int LIMIT=0.85e6 ; LL t[LIMIT] ; int len=0 ; LL N, ret=1 ; VI primes ; void doit(LL n, int i, bool isNew, LL* it) { if(isNew) { assert(1<=n && n<=N) ; it = lower_bound(it, t+len, N/n, greater<LL>()) ; maxi(ret, n*(*it)) ; } int p=primes[i] ; if(((double)p)*n<=N) doit(n*p, i, true, it) ; if(i+1<primes.size()) doit(n, i+1, false, it) ; } // MEET IN THE MIDDLE po zbiorach liczb pierwszych int main() { ios_base::sync_with_stdio(0) ; int k, p ; cin >> k >> N ; primes.resize(k) ; REP(i, k) cin >> primes[i] ; sort(ALL(primes)) ; DEBUG(primes) ; // Krok1: tablicuje liczby generowane przez najmniejsze liczby pierwsze t[0]=1 ; len=1 ; VI unused ; for(int p: primes) { int next=len ; LL M=N/p ; bool ok=true ; for(int i=0 ; i<len && ok ; i++) { for(LL a=t[i] ; a<=M && ok ; a*=p) { if(next<LIMIT) t[next++] = a*p ; else ok=false ; } } if(ok) { DEBUG("biore ", p) ; len=next ; } else { unused.PB(p) ; } } primes=unused ; DEBUG("zostaly:", primes) ; sort(t,t+len) ; reverse(t,t+len) ; //DEBUG(vector<LL>(t,t+len)) ; DEBUG(len) ; reverse(ALL(primes)) ; // Krok2: generuje rekrencyjnie liczby z pozostalych liczb pierwszych doit(1, 0, true, t) ; cout << ret << endl ; } |
English