結果
| 問題 | No.1036 Make One With GCD 2 |
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2020-05-01 10:26:28 |
| 言語 | C++14 (gcc 15.2.0 + boost 1.89.0) |
| 結果 |
TLE
(最新)
AC
(最初)
|
| 実行時間 | - |
| コード長 | 3,350 bytes |
| 記録 | |
| コンパイル時間 | 1,112 ms |
| コンパイル使用メモリ | 79,824 KB |
| 実行使用メモリ | 26,112 KB |
| 最終ジャッジ日時 | 2024-09-16 14:18:18 |
| 合計ジャッジ時間 | 9,300 ms |
|
ジャッジサーバーID (参考情報) |
judge3 / judge4 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | -- * 4 |
| other | TLE * 1 -- * 40 |
ソースコード
#include <cstdio>
#include <vector>
#include <cassert>
#include <iostream>
#include <cstdint>
#include <chrono>
using namespace std;
#define I64 int64_t
#define curtime chrono::system_clock::time_point
#define getcurtime chrono::system_clock::now
int mma(int x, int y)
{
return x < y ? y : x;
}
I64 getgcd(I64 x, I64 y)
{
I64 t = 0;
if(x < y){
while(x != 0){
if (y < x + x){
t = x;
x = y - x;
y = t;
} else {
t = x;
x = y % x;
y = t;
}
}
return y;
} else {
while(y != 0){
if(x < y + y){
t = y;
y = x - y;
x = t;
} else {
t = y;
y = x % y;
x = t;
}
}
return x;
}
}
I64 getgcd2(I64 x, I64 y)
{
I64 t;
while(0 < x){
t = x;
x = y % x;
y = t;
}
return y;
}
class SegTree{
public:
SegTree(int n);
void UpdateAll();
void Set(int idx, I64 v);
int RightBound(int left, int right);
vector<vector<I64>> stage;
vector<int> left_stage;
vector<int> sz_stage;
int stagenum;
};
void SegTree::UpdateAll()
{
for(int i = this->stagenum - 2; 0 <= i; i--){
int cnt = 1 << i;
vector<I64>& child = this->stage[i + 1];
vector<I64>& parent = this->stage[i];
for(int j = 0; j < cnt; j++){
parent[j] = getgcd2(child[2 * j], child[2 * j + 1]);
}
}
}
SegTree::SegTree(int n)
{
int stagenum = 1;
int mul = 1;
this->stage.push_back(vector<I64>(1, 0));
while(mul < n){
mul *= 2;
stagenum += 1;
this->stage.push_back(vector<I64>(mul, 0));
}
this->stagenum = stagenum;
this->left_stage.resize(n);
for(int i = 0; i < n; i++){
int sp = 0;
int sz = 1 << (stagenum - 1);
while(i % sz != 0){
sp += 1;
sz /= 2;
}
this->left_stage[i] = sp;
}
this->sz_stage.resize(n + 1);
int tmp = 1;
int sp = stagenum - 1;
for(int i = 1; i <= n; i++){
if(tmp * 2 == i){
tmp *= 2;
sp -= 1;
}
this->sz_stage[i] = sp;
}
}
void SegTree::Set(int idx, I64 v)
{
this->stage[this->stagenum - 1][idx] = v;
}
int SegTree::RightBound(int left, int right)
{
I64 ret = 0LL;
int retpos = left - 1;
int l = left;
int r = right;
int istage = mma(this->left_stage[left], this->sz_stage[right - left + 1]);
int stagenum = this->stagenum;
while(true){
int sz = 1 << (stagenum - istage - 1);
I64 tmp = getgcd(ret, this->stage[istage][l / sz]);
if(1 < tmp){
ret = tmp;
retpos = l + sz - 1;
if(retpos == right){ break; }
if(l + sz <= r){
l += sz;
istage = mma(this->left_stage[l], this->sz_stage[r - l + 1]);
} else { break; }
} else {
if (sz == 1){
break;
}
istage++;
r = l + sz - 2;
}
}
return retpos + 1;
}
int main(void)
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
curtime a = getcurtime();
int n;
cin >> n;
SegTree st(n);
for(int i = 0; i < n; i++){
I64 v;
cin >> v;
st.Set(i, v);
}
st.UpdateAll();
curtime b = getcurtime();
// cout << (b - a).count() / 1000000.0 << endl;
int z = n - 1;
I64 ret = 0;
for(int i = n - 1; 0 <= i; i--){
int p = st.RightBound(i, z);
ret = ret + n - p;
if(n < z) { z = n; }
}
cout << ret << endl;
curtime c = getcurtime();
// cout << (c - a).count() / 1000000.0 << endl;
}