FJUT Home_W的gcd(乱搞)题解

题意:

给出一个序列a1,a2,a3,……an。

HOME_W想在其中挖掘二元组,其中二元组的挖掘方法如下。

对于任意整数 l,r ,可得到一个二元组(l,gcd(al,al+1,……,ar))。

HOME_W 现在想知道对于所有的1<=l<=r<=n

他可以发掘出多少种不同的二元组

 

思路:

所以我们从最右边开始求。求第i个时,我们把a[i]压入vector,当做以i为右边界的情况,然后遍历i到末尾所有的gcd,更新gcd为gcd(gcd,a[i])。

新学了vecter::erase(iterator _First,iterator _Last),删除从fist到last的元素。q.erase(unique(q.begin(), q.end()), q.end()); unique(q.begin(), q.end())会返回去重后的end()地址,这样就直接把重复的删掉了。

代码:

#include<set>
#include<map>
#include<stack>
#include<cmath>
#include<queue>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
typedef long long ll;
const int maxn = 100000 + 10;
const int seed = 131;
const ll MOD = 1e9 + 7;
const int INF = 0x3f3f3f3f;
using namespace std;
ll a[maxn];
vector<ll> q;
ll gcd(ll a, ll b){
    return b == 0? a : gcd(b, a % b);
}
int main(){
    int n;
    scanf("%d", &n);
    for(int i = 1; i <= n; i++)
        scanf("%lld", &a[i]);
    ll ans = 0;
    q.clear();
    for(int i = n; i >= 1; i--){
        q.push_back(a[i]);
        int num = q.size();
        for(int j = 0; j < num; j++){
            int v = q[j];
            q[j] = gcd(q[j], a[i]);
        }
        q.erase(unique(q.begin(), q.end()), q.end());
        ans += q.size();
    }
    printf("%lld\n", ans);
    return 0;
}

 

posted @ 2018-10-16 00:00  KirinSB  阅读(244)  评论(0编辑  收藏  举报