結果
| 問題 |
No.1036 Make One With GCD 2
|
| コンテスト | |
| ユーザー |
noshi91
|
| 提出日時 | 2020-04-25 17:30:41 |
| 言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
AC
|
| 実行時間 | 1,369 ms / 2,000 ms |
| コード長 | 3,375 bytes |
| コンパイル時間 | 1,074 ms |
| コンパイル使用メモリ | 79,844 KB |
| 最終ジャッジ日時 | 2025-01-10 01:20:23 |
|
ジャッジサーバーID (参考情報) |
judge5 / judge3 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 4 |
| other | AC * 41 |
ソースコード
#define NDEBUG
#include <cassert>
#include <utility>
#include <vector>
template <class Semigroup> class disjoint_sparse_table {
public:
using value_structure = Semigroup;
using value_type = typename value_structure::value_type;
private:
using container_type = ::std::vector<::std::vector<value_type>>;
public:
using const_reference = typename container_type::value_type::const_reference;
using size_type = typename container_type::value_type::size_type;
protected:
static size_type msb(size_type c) {
#ifdef __has_builtin
return 31 - __builtin_clz(c);
#else
::std::size_t ret = 0;
if (c >> 16)
c >>= 16, ret += 16;
if (c >> 8)
c >>= 8, ret += 8;
if (c >> 4)
c >>= 4, ret += 4;
if (c >> 2)
c >>= 2, ret += 2;
return ret + (c >> 1);
#endif
}
container_type table;
public:
disjoint_sparse_table() : table() {}
template <class InputIterator>
disjoint_sparse_table(InputIterator first, InputIterator last) : table() {
table.emplace_back(first, last);
const size_type size = table.front().size();
for (size_type i = 2; i < size; i <<= 1) {
typename container_type::value_type v;
v.reserve(size);
for (size_type j = i; j < size; j += i << 1) {
v.emplace_back(table.front()[j - 1]);
for (size_type k = 2; k <= i; ++k)
v.emplace_back(
value_structure::operation(table.front()[j - k], v.back()));
v.emplace_back(table.front()[j]);
for (size_type k = 1; k < i && j + k < size; ++k)
v.emplace_back(
value_structure::operation(v.back(), table.front()[j + k]));
}
table.emplace_back(::std::move(v));
}
}
size_type size() const { return table.empty() ? 0 : table.front().size(); }
bool empty() const { return size() == 0; }
value_type fold_closed(const size_type first, const size_type last) const {
assert(first <= last);
assert(last < size());
if (first == last) {
return table.front()[first];
} else {
const size_type p = msb(first ^ last);
return value_structure::operation(
table[p][first ^ (static_cast<size_type>(1) << p) - 1],
table[p][last]);
}
}
const_reference operator[](const size_type index) const {
assert(index < size());
return table.front()[index];
}
};
#include <iostream>
#include <numeric>
#include <vector>
using u64 = unsigned long long;
class gcd_monoid {
public:
using value_type = u64;
static constexpr u64 operation(const u64 a, const u64 b) {
return std::gcd(a, b);
}
static constexpr u64 identity = 0;
};
int main() {
std::cin.tie(nullptr);
std::ios::sync_with_stdio(false);
int n;
std::cin >> n;
std::vector<u64> as(n);
for (int i = 0; i < n; i++)
std::cin >> as[i];
const disjoint_sparse_table<gcd_monoid> dst(as.begin(), as.end());
u64 ans = 0;
for (int i = 0; i < n; i++) {
int l = i;
u64 pre = as[i], lst = dst.fold_closed(i, n - 1);
while (lst != pre) {
int r = n, pl = l;
while (l + 1 < r) {
int m = (l + r) >> 1;
if (dst.fold_closed(i, m - 1) != pre)
r = m;
else
l = m;
}
if (pre == 1)
ans += l - pl;
pre = dst.fold_closed(i, r - 1);
}
if (lst == 1)
ans += n - l;
}
std::cout << ans << std::endl;
return 0;
}
noshi91