HDU 5288 OO’s Sequence(贡献)
题意:
$N\le 10^5的序列,A_i\le 10^4$
$f(l, r):=区间中除自己以外都不是自己的约数的a_i的个数$
$求\sum_{i=1}^{n}\sum_{j=i}^{n}f(i,j) mod (10^{9}+7)$
分析:
$对于a_i,对于它的任意约数x,假设离它最近的约数的位置是pre_{x}和nxt_x$
$那么a_i能贡献的区间,显然左端点的选择是(pre_x, i],右端点的选择是[i, nxt_i)$
$那么对答案的贡献是(i-pre_x)\cdot(nxt_x-i)$
$时间复杂度是O(n\sqrt{n}),约数级别是O(\sqrt{n})的$
代码:
//
// Created by TaoSama on 2016-04-12
// Copyright (c) 2016 TaoSama. All rights reserved.
//
#pragma comment(linker, "/STACK:102400000,102400000")
#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <string>
#include <set>
#include <vector>
using namespace std;
#define pr(x) cout << #x << " = " << x << " "
#define prln(x) cout << #x << " = " << x << endl
const int N = 1e5 + 10, INF = 0x3f3f3f3f, MOD = 1e9 + 7;
int n, a[N];
int pre[N];
vector<int> divisors[N];
void gao() {
for(int i = 1; i <= 1e4; ++i)
for(int j = i; j <= 1e4; j += i)
divisors[j].push_back(i);
}
int main() {
#ifdef LOCAL
freopen("C:\\Users\\TaoSama\\Desktop\\in.txt", "r", stdin);
// freopen("C:\\Users\\TaoSama\\Desktop\\out.txt","w",stdout);
#endif
ios_base::sync_with_stdio(0);
gao();
while(scanf("%d", &n) == 1) {
for(int i = 1; i <= n; ++i) scanf("%d", a + i);
map<int, int> last;
for(int i = 1; i <= n; ++i) {
pre[i] = 0;
for(int d : divisors[a[i]]) pre[i] = max(pre[i], last[d]);
last[a[i]] = i;
}
last.clear();
int ans = 0;
for(int i = n; i; --i) {
int nxt = n + 1;
for(int d : divisors[a[i]]) if(last[d]) nxt = min(nxt, last[d]);
ans += 1LL * (i - pre[i]) * (nxt - i) % MOD;
if(ans >= MOD) ans -= MOD;
last[a[i]] = i;
}
printf("%d\n", ans);
}
return 0;
}