思维题 HDOJ 5288 OO’s Sequence

本文介绍了一个解决HDOJ5288问题的算法,涉及到枚举因子、更新左侧右侧接近位置以及计算贡献值等步骤,通过C++代码实现并详细解释了每一步的逻辑。

 

题目传送门

 1 /*
 2     定义两个数组,l[i]和r[i]表示第i个数左侧右侧接近它且值是a[i]因子的位置,
 3         第i个数被选择后贡献的值是(r[i]-i)*(i-l[i]),每个数都枚举它的因子,更新l[i], r[i],复杂度O(n*sqrt(a[i]))
 4 */
 5 #include <cstdio>
 6 #include <cmath>
 7 #include <algorithm>
 8 #include <cstring>
 9 #include <map>
10 using namespace std;
11 
12 const int MAXN = 1e5 + 10;
13 const int INF = 0x3f3f3f3f;
14 const int MOD = 1e9 + 7;
15 int a[MAXN];
16 int l[MAXN], r[MAXN];
17 int pos[10010];
18 
19 int main(void)  {       //HDOJ 5288 OO’s Sequence
20     //freopen ("1001.in", "r", stdin);
21     int n;
22     while (scanf ("%d", &n) == 1)   {
23         for (int i=1; i<=n; ++i)    {
24             scanf ("%d", &a[i]);
25         }
26         
27         int ans = 0;
28         memset (pos, 0, sizeof (pos));
29         memset (l, 0, sizeof (l));
30         for (int i=1; i<=n; ++i)    {
31             for (int j=1; j<=sqrt (a[i]); ++j)    {
32                 if (a[i] % j == 0)  {
33                     if (pos[j] > l[i])  l[i] = pos[j];
34                     if (pos[a[i]/j] > l[i])    l[i] = pos[a[i]/j];
35                 }
36             }
37             pos[a[i]] = i;
38         }
39         for (int i=1; i<=10000; ++i)    pos[i] = n + 1;
40         for (int i=1; i<=n; ++i)    r[i] = n + 1;
41         for (int i=n; i>=1; --i)    {
42             for (int j=1; j<=sqrt (a[i]); ++j)    {
43                 if (a[i] % j == 0)  {
44                     if (pos[j] < r[i])  r[i] = pos[j];
45                     if (pos[a[i]/j] < r[i])    r[i] = pos[a[i]/j];
46                 }
47             }
48             pos[a[i]] = i;
49         }
50         for (int i=1; i<=n; ++i)    {
51             ans = (ans + (r[i] - i) * (i - l[i]) % MOD) % MOD;
52         }
53         printf ("%d\n", ans);
54     }
55 
56     return 0;
57 }

 

转载于:https://www.cnblogs.com/Running-Time/p/4667014.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值