/* vim: set ts=4 sts=4 sw=4 si foldmethod=marker: */ // {{{ includes // IO #include #include #include #include #include // Utility #include #include #include #include #include #include #include #include // Data structures #include #include #include #include #include #include #include #include // I want easy access to STL and things like hash_map using namespace std; using namespace std::tr1; // Needed for hash_map /* namespace __gnu_cxx { template<> struct hash { size_t operator()(const std::string& x) const { return hash()(x.c_str()); } }; } */ // }}} // {{{ utility routines and such // stolen from http://www.ddj.com/cpp/184403801 template class StringTok { public: StringTok(const T& seq, typename T::size_type pos = 0) : seq_(seq) , pos_(pos) { } T operator()(const T& delim); private: const T& seq_; typename T::size_type pos_; }; template T StringTok::operator()(const T& delim) { T token; if(pos_ != T::npos) { // start of found token typename T::size_type first(seq_.find_first_not_of(delim.c_str(), pos_)); if (first != T::npos) { // length of found token typename T::size_type num(seq_.find_first_of(delim.c_str(), first) - first); // do all the work off to the side token = seq_.substr(first, num); // done; now commit using // nonthrowing operations only pos_ = first + num; if (pos_ != T::npos) ++pos_; if (pos_ >= seq_.size()) pos_ = T::npos; } } return token; } // stolen from http://www.gotw.ca/gotw/029.htm for case-insensitive lexicographic compares struct ci_char_traits : public std::char_traits { static bool eq(char c1, char c2) { return toupper(c1) == toupper(c2); } static bool ne(char c1, char c2) { return toupper(c1) != toupper(c2); } static bool lt(char c1, char c2) { return toupper(c1) < toupper(c2); } static int compare(const char* s1, const char* s2, size_t n) { return strncmp(s1, s2, n); } static const char* find(const char* s, int n, char a) { while(n-- > 0 && toupper(*s) != toupper(a)) { ++s; } return s; } }; // no boost makes c++ angry; lexical cast comes in handy for string <=> int conversion without expliucitly writing out the streams all the time. template T lexical_cast(const S& arg) { stringstream interpreter; T result; if (!(interpreter << arg) || !(interpreter >> result) || !(interpreter >> std::ws).eof()) throw logic_error("bad lexical_cast"); return result; } // }}} // {{{ utility typedefs typedef vector vs; typedef vector vi; typedef vector vl; typedef vector vll; typedef map mll; typedef std::basic_string ci_string; // }}} void yesno(bool div, long long n, long long m) { cout << m << ((div) ? " divides " : " does not divide ") << n << "!" << endl; } void prime_factorization(long long x, vector& cache) { long long i, c; c = x; while ((c%2) == 0) { cache.push_back(2); c /= 2; } i = 3; while (i < (sqrt(c)+1)) { if ((c%i) == 0) { cache.push_back(i); c /= i; } else i += 2; } if (c > 1) cache.push_back(c); } int get_powers(long long n, long long p) { long long res = 0; for (long long power = p ; power <= n ; power *= p) res += n/power; return res; } int main() { long long n, m; while (cin >> n >> m) { if (0 == m) yesno(false, n, m); else if (m <= n) yesno(true, n, m); else { vll m_factors; prime_factorization(m, m_factors); mll m_factors_rotated; int count(0); for (vll::const_iterator i(m_factors.begin()), ie(m_factors.end()); i != ie; ++i) { count++; if (i + 1 == ie || *i != *(i + 1)) { m_factors_rotated[*i] = count; count = 0; } } bool fail(false); for (mll::const_iterator i(m_factors_rotated.begin()), ie(m_factors_rotated.end()); i != ie; ++i) { int count_powers(get_powers(n, i->first)); if (!count_powers) { fail = true; break; } if (i->second > count_powers) { fail = true; break; } } yesno(!fail, n, m); } } return 0; }