結果
| 問題 |
No.1036 Make One With GCD 2
|
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2020-04-24 23:12:45 |
| 言語 | C++14 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
AC
|
| 実行時間 | 1,269 ms / 2,000 ms |
| コード長 | 3,589 bytes |
| コンパイル時間 | 1,753 ms |
| コンパイル使用メモリ | 173,476 KB |
| 実行使用メモリ | 15,568 KB |
| 最終ジャッジ日時 | 2024-09-16 13:31:22 |
| 合計ジャッジ時間 | 18,190 ms |
|
ジャッジサーバーID (参考情報) |
judge2 / judge3 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 4 |
| other | AC * 41 |
ソースコード
#include <bits/stdc++.h>
using namespace std::literals::string_literals;
using i64 = std::int_fast64_t;
using std::cout;
using std::endl;
using std::cin;
template<typename T>
std::vector<T> make_v(size_t a){return std::vector<T>(a);}
template<typename T,typename... Ts>
auto make_v(size_t a,Ts... ts){
return std::vector<decltype(make_v<T>(ts...))>(a,make_v<T>(ts...));
}
#ifndef INCLUDED_SEGMENT_TREE_HPP
#define INCLUDED_SEGMENT_TREE_HPP
#include <cstdint>
#include <vector>
#include <functional>
template<class Monoid>
class segment_tree {
public:
using T = typename Monoid::value_type;
using size_type = std::uint_fast32_t;
using updator = std::function<T(T)>;
using checker = std::function<bool(T)>;
private:
const size_type size_;
size_type height_;
public:
std::vector<T> data;
private:
const size_type get_height(size_type size) const {
size_type height = 1;
while(1 << height <= size) height++;
return height;
}
const size_type base_size() const { return 1 << height_; }
void meld(size_type index) {
data[index] = Monoid::operation(data[index << 1 ^ 0], data[index << 1 ^ 1]);
}
public:
segment_tree() = default;
segment_tree(segment_tree&&) = default;
segment_tree(const segment_tree&) = default;
segment_tree(size_type size)
: size_(size) {
height_ = get_height(size);
data.assign(base_size() << 1, T{});
}
T fold(size_type left, size_type right) {
T l_value = T{};
T r_value = T{};
for(left += base_size(), right += base_size();
left < right;
left >>= 1, right >>= 1) {
if(left & 1) l_value = Monoid::operation(l_value, data[left++]);
if(right & 1) r_value = Monoid::operation(data[--right], r_value);
}
return Monoid::operation(std::move(l_value), std::move(r_value));
}
void update(size_type index, const updator& update) {
index += base_size();
data[index] = update(data[index]);
while(index >>= 1) meld(index);
}
void update(size_type index, const T& value) { update(index, [&value](const T& x) { return Monoid::operation(x, value); }); }
void change(size_type index, const T& value) { update(index, [&value](const T& x) { return value; }); }
const size_type search(size_type left, const checker& check) {
T val = T{};
size_type k = left + base_size();
while(true) {
if(check(Monoid::operation(val, data[k]))) {
val = Monoid::operation(val, data[k]);
if(k & 1) {
if((k + 1) & k) k = (k + 1) >> 1;
else return size();
} else {
k = k + 1;
}
} else {
if(k < base_size()) {
k = k << 1 ^ 0;
} else {
return k - base_size();
}
}
}
}
const T operator[](size_type index) const { return data[index + base_size()]; }
const size_type size() const { return size_; }
const bool empty() const { return data.empty(); }
};
template<class T>
struct monoid {
using value_type = T;
static value_type operation(const value_type& a, const value_type& b) { return a + b; };
};
// @docs docs/segment_tree.md
#endif
struct node {
i64 val;
node(i64 val = 0): val(val) {}
node operator+(const node& r) const { return node(std::__gcd(val, r.val)); }
};
int main() {
int n; scanf("%d", &n); std::vector<i64> a(n);
for(int i = 0; i < n; i++) scanf("%lld", &a[i]);
segment_tree<monoid<node>> seg(n);
for(int i = 0; i < n; i++) seg.change(i, a[i]);
i64 now = 0, ans = 0;
for(int i = 0, left = 1; i < n; i++) {
left = std::max(left, i + 1);
now = seg.fold(i, left).val;
while(left < n and now != 1) now = std::__gcd(now, a[left++]);
if(now == 1) ans += n - left + 1;
}
printf("%lld\n", ans);
return 0;
}