結果
| 問題 |
No.719 Coprime
|
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2018-07-29 03:41:54 |
| 言語 | C++14 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
AC
|
| 実行時間 | 1,339 ms / 3,000 ms |
| コード長 | 12,656 bytes |
| コンパイル時間 | 1,690 ms |
| コンパイル使用メモリ | 141,216 KB |
| 実行使用メモリ | 31,100 KB |
| 最終ジャッジ日時 | 2024-07-07 05:51:35 |
| 合計ジャッジ時間 | 9,279 ms |
|
ジャッジサーバーID (参考情報) |
judge2 / judge5 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| other | AC * 61 |
ソースコード
#include <iostream>
#include <queue>
#include <map>
#include <list>
#include <vector>
#include <string>
#include <stack>
#include <limits>
#include <climits>
#include <cassert>
#include <fstream>
#include <cstring>
#include <cmath>
#include <bitset>
#include <iomanip>
#include <algorithm>
#include <functional>
#include <cstdio>
#include <ciso646>
#include <set>
#include <array>
#include <unordered_map>
#include <unordered_set>
#include <type_traits>
using namespace std;
#define FOR(i,a,b) for (int i=(a);i<(b);i++)
#define RFOR(i,a,b) for (int i=(b)-1;i>=(a);i--)
#define REP(i,n) for (int i=0;i<(n);i++)
#define RREP(i,n) for (int i=(n)-1;i>=0;i--)
#define VEC2(T, N, M) vector<T>(N, vector<T>(M));
#define inf 0x3f3f3f3f3f3f3f3f
#define PB push_back
#define MP make_pair
#define ALL(a) (a).begin(),(a).end()
#define SET(a,c) memset(a,c,sizeof a)
#define CLR(a) memset(a,0,sizeof a)
#define VS vector<string>
#define VI vector<ll>
#define DEBUG(x) cout<<#x<<": "<<x<<endl
#define MIN(a,b) (a>b?b:a)
#define MAX(a,b) (a>b?a:b)
#define pi 2*acos(0.0)
#define INFILE() freopen("in0.txt","r",stdin)
#define OUTFILE()freopen("out0.txt","w",stdout)
#define ll long long
#define ull unsigned long long
#define pii pair<ll,ll>
#define pcc pair<char,char>
#define pic pair<ll,char>
#define pci pair<char,ll>
#define eps 1e-14
#define FST first
#define SEC second
#define SETUP cin.tie(0), ios::sync_with_stdio(false), cout << setprecision(15) << std::fixed;
template <class T>
using vec2 = std::vector<vector<T>>;
namespace {
struct input_returnner {
ll N; input_returnner(ll N_ = 0) :N(N_) {}
template<typename T> operator vector<T>() const { vector<T> res(N); for (auto &a : res) cin >> a; return std::move(res); }
template<typename T> operator T() const { T res; cin >> res; return res; }
template<typename T> T operator - (T right) { return T(input_returnner()) - right; }
template<typename T> T operator + (T right) { return T(input_returnner()) + right; }
template<typename T> T operator * (T right) { return T(input_returnner()) * right; }
template<typename T> T operator / (T right) { return T(input_returnner()) / right; }
template<typename T> T operator << (T right) { return T(input_returnner()) << right; }
template<typename T> T operator >> (T right) { return T(input_returnner()) >> right; }
};
template<typename T> input_returnner in() { return in<T>(); }
input_returnner in() { return input_returnner(); }
input_returnner in(ll N) { return std::move(input_returnner(N)); }
}
template<typename T>
istream& operator >> (istream& is, vector<T>& vec) {
for (T& x : vec) is >> x;
return is;
}
template < typename T >
struct is_vector : std::false_type {};
template < typename T >
struct is_vector<std::vector<T>> : std::true_type {};
template < typename T >
constexpr bool is_vector_v = is_vector<T>::value;
template <typename T>
std::ostream& operator<< (std::ostream& out, const std::vector<T>& v) {
if (!v.empty()) {
for (int i = 0; i < v.size(); ++i) {
out << v[i] << (i == v.size() - 1 ? "\n" : (is_vector_v<T> ? "" : ", "));
}
}
return out;
}
namespace std {
// ref: https://stackoverflow.com/questions/7110301/generic-hash-for-tuples-in-unordered-map-unordered-set
template <class T>
inline void hash_combine(std::size_t& seed, T const& v)
{
seed ^= std::hash<T>()(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
}
// Recursive template code derived from Matthieu M.
template <class Tuple, size_t Index = std::tuple_size<Tuple>::value - 1>
struct HashValueImpl
{
static void apply(size_t& seed, Tuple const& tuple)
{
HashValueImpl<Tuple, Index - 1>::apply(seed, tuple);
hash_combine(seed, std::get<Index>(tuple));
}
};
template <class Tuple>
struct HashValueImpl<Tuple, 0>
{
static void apply(size_t& seed, Tuple const& tuple)
{
hash_combine(seed, std::get<0>(tuple));
}
};
template <typename ... TT>
struct hash<std::tuple<TT...>>
{
size_t operator()(std::tuple<TT...> const& tt) const
{
size_t seed = 0;
HashValueImpl<std::tuple<TT...> >::apply(seed, tt);
return seed;
}
};
template <class T, class U>
class hash<std::pair<T, U>> {
public:
size_t operator()(const std::pair<T, U>& x) const {
return hash<std::tuple<T, U>>()(std::tie(x.first, x.second));
}
};
}
// ref: https://stackoverflow.com/questions/6245735/pretty-print-stdtuple
namespace aux {
template<std::size_t...> struct seq {};
template<std::size_t N, std::size_t... Is>
struct gen_seq : gen_seq<N - 1, N - 1, Is...> {};
template<std::size_t... Is>
struct gen_seq<0, Is...> : seq<Is...> {};
template<class Ch, class Tr, class Tuple, std::size_t... Is>
void print_tuple(std::basic_ostream<Ch, Tr>& os, Tuple const& t, seq<Is...>) {
using swallow = int[];
(void)swallow {
0, (void(os << (Is == 0 ? "" : ", ") << std::get<Is>(t)), 0)...
};
}
} // aux::
template<class Ch, class Tr, class... Args>
auto operator<<(std::basic_ostream<Ch, Tr>& os, std::tuple<Args...> const& t)
-> std::basic_ostream<Ch, Tr>&
{
os << "(";
aux::print_tuple(os, t, aux::gen_seq<sizeof...(Args)>());
return os << ")";
}
template<class S, class T>
std::ostream & operator<<(std::ostream & os, const std::pair<S, T> & p)
{
return os << "(" << p.first << ", " << p.second << ")";
}
// ref: https://stackoverflow.com/questions/8542591/c11-reverse-range-based-for-loo�Fp
template <typename T>
struct reversion_wrapper { T& iterable; };
template <typename T>
auto begin(reversion_wrapper<T> w) { return std::rbegin(w.iterable); }
template <typename T>
auto end(reversion_wrapper<T> w) { return std::rend(w.iterable); }
template <typename T>
reversion_wrapper<T> REV(T&& iterable) { return { iterable }; }
ll MOD = 1e9 + 7;
class prime;
void solve();
signed main() {
SETUP;
solve();
#ifdef _DEBUG
system("pause");
#endif
return 0;
}
#define int ll
// template
template<class T>
struct fkvector {
public:
vector<T> v;
fkvector(size_t size) :v(size) {}
size_t size() const { return v.size(); }
T& operator [] (const int index) {
return v[index];
}
T dot(const fkvector<T>& right) {
assert(v.size() == right.size());
T res = 0;
for (int i = 0; i < right.size(); ++i) {
res += v[i] * right.v[i];
}
return res;
}
void operator = (const fkvector<T>& right) {
v.clear();
v.resize(right.size());
copy(right.v.begin(), right.v.end(), v.begin());
}
fkvector<T> operator + (const fkvector<T>& right) {
assert(v.size() == right.size());
fkvector<T> res(v.size());
for (size_t i = 0; i < v.size(); ++i) {
res[i] = v[i] + right.v[i];
}
return res;
}
fkvector<T> operator - (const fkvector<T>& right) {
assert(v.size() == right.size());
fkvector<T> res(v.size());
for (size_t i = 0; i < v.size(); ++i) {
res[i] = v[i] - right.v[i];
}
return res;
}
void operator += (const fkvector<T>& right) {
assert(v.size() == right.size());
*this = *this + right;
}
void operator -= (const fkvector<T>& right) {
assert(v.size() == right.size());
*this = *this - right;
}
void print() {
cout << "{";
for (int i = 0; i < v.size()-1; ++i) {
cout << v[i] << ", ";
}
cout << v.back();
cout << "}" << endl;
}
};
template<class T>
struct fkmat {
vector<vector<T> > mat;
size_t getRowCount() const { return mat.size(); }
size_t getColomnCount() const { return mat[0].size(); }
size_t size() const { return mat.size(); }
fkmat(size_t size_row,size_t size_colomn):mat(size_row, vector<T>(size_colomn)) {}
vector<T>& operator [] (const int index) { return mat[index]; }
//Identity matrix
fkmat<T> Identity() {
for (int i = 0; i < mat.size(); ++i) {
mat[i][i] = 1;
}
return *this;
}
void operator = (const fkmat<T>& right) {
mat.clear();
mat.resize(right.size());
for (int i = 0; i < right.size(); ++i) {
mat[i] = right.mat[i];
}
}
fkmat<T> operator + (const fkmat<T>& right) {
fkmat<T> res(getRowCount(), getColomnCount());
for (int i = 0; i < mat.size(); ++i) {
for (int j = 0; j < mat[i].size(); ++j) {
res[i][j] = mat[i][j] + right.mat[i][j];
}
}
return res;
}
fkmat<T> operator - (const fkmat<T>& right) {
fkmat<T> res(getRowCount(), getColomnCount());
for (int i = 0; i < mat.size(); ++i) {
for (int j = 0; j < mat[i].size(); ++j) {
res[i][j] = mat[i][j] - right.mat[i][j];
}
}
return res;
}
fkmat<T> operator * (const fkmat<T>& right) {
fkmat<T> res(getRowCount(), getColomnCount());
assert(getColomnCount() == right.getRowCount());
for (int r = 0; r < getRowCount(); ++r) {
for (int c = 0; c < right.getColomnCount(); ++c) {
for (int k = 0; k < getColomnCount(); ++k) {
res[r][c] += mat[r][k] * right.mat[k][c];
res[r][c] %= MOD;
}
}
}
return res;
}
void operator += (const fkmat<T>& right) {
for (int i = 0; i < mat.size(); ++i) {
for (int j = 0; j < mat[i].size(); ++j) {
mat[i][j] += right.mat[i][j];
}
}
}
void operator -= (const fkmat<T>& right) {
for (int i = 0; i < mat.size(); ++i) {
for (int j = 0; j < mat[i].size(); ++j) {
mat[i][j] -= right.mat[i][j];
}
}
}
void operator *= (const fkmat<T>& right) {
*this = *this * right;
}
//power n
void pow(long long n, fkmat<T>* dst) {
dst->Identity();
fkmat<T> x(getRowCount(), getColomnCount());
x.mat = mat;
while (n > 0) {
if (n & 1) *dst = *dst * x;
x *= x;
x %= MOD;
n >>= 1;
}
}
//power n
void pow(long long n) {
fkmat<T> res(getRowCount(), getColomnCount());
res = fkmat<T>(getRowCount(), getColomnCount()).Identity();
fkmat<T> x(getRowCount(), getColomnCount());
x = *this;
while (n > 0) {
if (n & 1) res = res * x;
x *= x;
n >>= 1;
}
*this = res;
}
void print() {
for (size_t i = 0; i < mat.size(); ++i) {
for (size_t j = 0; j < mat[i].size(); ++j) {
cout << mat[i][j] << " ";
}
cout << endl;
}
}
};
int gcd(int a, int b) {
return b != 0 ? gcd(b, a % b) : a;
}
class prime {
private:
public:
std::vector<int> primes;
std::vector<bool> isPrime;
prime(int num = 0) {
if (num == 0) return;
isPrime.resize(num + 1);
fill(isPrime.begin(), isPrime.end(), true);
int ma = sqrt(num) + 1;
isPrime[0] = isPrime[1] = false;
int cnt = 0;
for (int i = 2; i <= ma; ++i) if (isPrime[i]) {
for (int j = 2; i*j <= num; ++j) {
isPrime[i*j] = false;
cnt++;
}
}
primes.reserve(cnt);
for (int i = 0; i<isPrime.size(); ++i) if (isPrime[i]) {
primes.push_back(i);
}
}
bool IsPrime(int num) {
if (num < isPrime.size()) return isPrime[num];
for (auto p : primes) {
if (num%p == 0) return false;
}
int ma = sqrt(num) + 1;
for (int i = primes.back(); i <= ma; i += 2) {
if (num%i == 0) return false;
}
return true;
}
std::map<int, int> GetFactor(int num) {
std::map<int, int> res;
int ma = sqrt(num) + 1;
int a = 2;
auto it = primes.begin();
while (num >= a*a) {
if (num%a == 0) {
res[a]++;
num /= a;
}
else {
if (it == primes.end()) ++a;
else {
++it;
a = *it;
}
}
}
res[num]++;
return res;
}
};
unordered_map<pair<int, int>, int> memo; // {depth, mask} = res;
int f(vector<vector<int> >& dps, int depth, int mask) {
if (depth == 0) return dps[0][mask];
if (memo.find({ depth, mask }) != memo.end()) return memo[{depth, mask}];
int res = 0;
for(int i = 0;;i = (i-mask) & mask){ // take out i
res = max(res, f(dps, depth - 1, mask - i) + dps[depth][i]);
if (i == mask) break;
}
memo[{depth, mask}] = res;
return res;
}
void solve() {
int N; cin >> N;
if (N == 2) {
cout << 2 << endl;
return;
}
if (N == 3) {
cout << 5 << endl;
return;
}
prime primes(N);
unordered_map<int, int> prime2Num;
REP(i,primes.primes.size()){
prime2Num[primes.primes[i]] = i;
}
auto rootPrime = upper_bound(ALL(primes.primes), sqrt(N))-1;
int maxPrime = *rootPrime;
int M = (rootPrime - primes.primes.begin())+1;
int res = 0;
vector<vector<int> > dps(prime2Num.size() - M+1 , vector<int>(1 << M));
FOR(i, 2, N+1) {
auto factors = primes.GetFactor(i);
int bits = 0;
int maxFactor = 0;
for (auto &p : factors) {
maxFactor = max(p.first, maxFactor);
if (p.first <= maxPrime){
bits += (1 << prime2Num[p.first]);
}
}
if (maxFactor <= maxPrime) {
dps[0][bits] = max(dps[0][bits], i);
}
else {
int num = prime2Num[maxFactor] - M;
dps[num+1][bits] = max(dps[num][bits], i);
}
}
{
vector<int>& dp = dps[0];
FOR(tar, 1, dp.size()) {
for(int i = 0;;i = (i-tar) & tar){
int invI = tar - i;
dp[tar] = max(dp[tar], dp[i]+dp[invI]);
if (i == tar) break;
}
}
}
cout << f(dps, dps.size() - 1, (1 << M) - 1) << endl;
}