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; }