HDU5288 OO’s Sequence

Problem Description

OO has got a array A of size n ,defined a function f(l,r) represent the number of i (l<=i<=r) , that there‘s no j(l<=j<=r,j<>i) satisfy ai mod aj=0,now OO want to know

∑i=1n∑j=inf(i,j) mod (109+7).

Input

There are multiple test cases. Please process till EOF.
In each test case: 
First line: an integer n(n<=10^5) indicating the size of array
Second line:contain n numbers ai(0<ai<=10000)

Output

For each tests: ouput a line contain a number ans.

Sample Input

5
1 2 3 4 5

Sample Output

23

Author

FZUACM

Source

2015 Multi-University Training Contest 1

一考思维,就想GG,搞了好长时间

这道题目的解法是: 通过预处理,记录 a[i] 的左右边界(所谓的左右边界时 在从 a[i] 当前位置往左往右找,找到左边第一个和右边第一个能够整除 a[i] 的数,这两个数就是a[i]的左右边界)然后记录到 l[] & r[] 中, 这样 a[i] 对 ans 的贡献是 (i - l[i]) * (r[i] - i);

在预处理 l[] 数组时,用pre[j]标记一下 j (表示 j 最后一次出现的位置),如果 j 在之前已经遇到过且右边界没有被更新过,就将 pre[j] 的边界更新到当前 i 所在的位置。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#define LL long long
#define MAXN 100010
using namespace std;
const LL MOD = 1e9 + 7;
int a[MAXN];
LL l[MAXN], r[MAXN], pre[MAXN], last[MAXN];
int main() {
      int n;
      while(~scanf("%d", &n)) {
            for(int i = 1; i <= n; ++i) {
                  scanf("%d", a + i);
                  l[i] = 0, r[i] = n+1;
            }
            memset(pre, 0, sizeof(pre));
            memset(last, 0, sizeof(last));

            for(int i = 1; i <= n; ++i) {
                  for(int j = a[i]; j <= 10000; j += a[i]) {           //通过这个循环,如果a[i]是之前一个数的因子,一定会在后边遇到
                        if(pre[j] != 0 && r[pre[j]] == n+1) {               //这个数字 j (j = x * a[i])之前已经出现,且右边界是最右端
                              r[pre[j]] = i;                                  //这时更新pre[j]的右端, pre[j] 表示的是 j 最后出现的位置
                        }
                  }
                  pre[a[i]] = i;   //当前pre[a[i]] 最后出现的位置是 i
            }

            for(int i = n; i > 0; --i) {
                  for(int j = a[i]; j <= 10000; j += a[i]) {
                        if(last[j] != 0 && l[last[j]] == 0) {
                              l[last[j]] = i;
                        }
                  }
                  last[a[i]] = i;
            }
            LL ans = 0;
            for(int i = 1; i <= n; ++i) {
                  ans = (LL) (ans % MOD + (LL)(((i-l[i])*(r[i]-i)%MOD)%MOD));
                  ans %= MOD;
            }
            cout << ans << endl;
      }
      return 0;
}
时间: 2024-10-07 02:32:07

HDU5288 OO’s Sequence的相关文章

解题报告 之 HDU5288 OO&#39; s Sequence

解题报告 之 HDU5288 OO' s Sequence Description OO has got a array A of size n ,defined a function f(l,r) represent the number of i (l<=i<=r) , that there's no j(l<=j<=r,j<>i) satisfy a imod a j=0,now OO want to know () Input There are multipl

hdu5288 OO’s Sequence(质因子分解+二分)

题目:http://acm.hdu.edu.cn/showproblem.php?pid=5288 题意:区间[L,R],若L<=i<=R,对于所有的i,满足a[i]%a[j]!=0(i!=j)则i对答案的贡献+1.求出所有区间的答案和,其中1<=L<=R<=N. 分析:求出每个数对答案的贡献即可.对于每个a[i],求左边离a[i]最近且可以整出a[i]的位置L[i]和右边离a[i]最近且可以整出a[i]的位置R[i],那么a[i]对答案的贡献就是(R[i]-i)*(i-L[

HDU5288——OO’s Sequence(2015多校-1001)

http://acm.hdu.edu.cn/showproblem.php?pid=5288 一句话,这题目就是考智商的题...可怜我这个新手智商低~T_T 言归正传:题意很容易理解,就是讲一个数组的可以组成的所有区间的,该区间所有不能整除该区间其他数的个数的和. 解决办法就是:找到一个数的左右最近的两个值恰好为该数的因子的位置分别为L[i],R[i],那么在区间(L[i],R[i])内a[i]是该区间的一个所有数的值都不能整除该数的值.所以a[i]可以作为答案的个数为(L[i]-i)*(i-R

解题报告 之 HDU5288 OO&amp;#39; s Sequence

解题报告 之 HDU5288 OO' s Sequence Description OO has got a array A of size n ,defined a function f(l,r) represent the number of i (l<=i<=r) , that there's no j(l<=j<=r,j<>i) satisfy a imod a j=0,now OO want to know Input There are multiple t

hdu5288(2015多校1)OO’s Sequence

OO's Sequence Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Total Submission(s): 353    Accepted Submission(s): 117 Problem Description OO has got a array A of size n ,defined a function f(l,r) represent the nu

[HDOJ5288]OO&#39;s Sequence

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5288 转换成求从1到n可以整除A[i]的区间的数量.找离最近的A[i]最近的可以整除A[i]的l和r,因为再往左或者右必然包含l和r假如[l,i]有x个数字,[i,r]有y个数字,那么A[i]的贡献即(x+1)*(y+1)求A[i]对ans的贡献综合即求离A[i]最近的可以被A[i]整除的数 1 #include <cstdio> 2 #include <cstdlib> 3 #inc

hdu 5288 OO’s Sequence 分解因子

链接:http://acm.hdu.edu.cn/showproblem.php?pid=5288 OO's Sequence Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Total Submission(s): 588    Accepted Submission(s): 209 Problem Description OO has got a array A of

Hdu 5288 OO’s Sequence 2015多小联赛A题

OO's Sequence Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Total Submission(s): 1751    Accepted Submission(s): 632 Problem Description OO has got a array A of size n ,defined a function f(l,r) represent the n

HDU 5288 OO’s Sequence (暴力枚举因子)

题目链接:HDU 5288 OO's Sequence 题意:给出一个n,表示n个数的序列,函数f(l,r)定义,在l,r区间中存在多少个数,不能被其他数整除.求累加所有子区间的函数值 思路:从ai的小范围入手 1.a不能被b整除,即a的所有因子中不存在b,所以打表枚举所有的数的因子. 2.找到一个数(位置为i)满足条件时最左端l和最右端r,(i-l)*(r-i)就是对答案的贡献. AC代码: #include <stdio.h> #include <algorithm> #inc