hdu 5288 OO’s Sequence

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5288

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=1->n)∑(j=i->n)f(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

题意:给一个大小为n的数组a[i]以及n各数,求所有f(le,ri)的和([le,ri]是[1,n]的所有子区间),f(le,ri)是指区间[le,ri]里每一个满足一定条件的a[i]的个数,

条件是区间[le,ri]里没有一个不等于i的j使得a[i]%a[j]=0;(如果le==ri,区间只有一个a[i],这个是满足条件的,因为确实是没有一个不等于i的j,那就更不用谈什么模了。)

思路:数据大,暴力无解,从a[i]%a[j]=0入手,这样的a[j]一定是a[i]的因子,也就是说一个区间一旦有了a[i]的因子a[i]对答案就没有贡献了,那么对于每一个a[i]
向两边扩张区间,遇到离a[i]最近的一个因子,存下位置le[i],ri[i],那么a[i]有用的最大区间就是[le[i],ri[i]],然后这个怎么算a[i]对答案的贡献,只要在这个区间包含到a[i]

的所有子区间都满足条件并且贡献答案1,那么就算包含a[i]的区间个数,既然包含a[i],那么子区间的起点le可以从le[i]取到i,终点从i取到ri[i],总共有(i-le[i])*(ri[i]-i)个;

这样还有个问题,如从i开始直接往两边去一个一个找端点还是会超时的,需要优化,a[i]只有10000,不大因子个数也不多,那么用筛法的思想对每个数把其位置添加到这个数的

倍数后面,以表示它的倍数有这个因子;

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<string>
 4 #include<algorithm>
 5 #include<set>
 6 #include<map>
 7 #include<queue>
 8 #include<vector>
 9 #include<iterator>
10 #include<utility>
11 #include<sstream>
12 #include<iostream>
13 #include<cmath>
14 #include<stack>
15 using namespace std;
16 const int INF=1000000007;
17 const double eps=0.00000001;
18 const int maxn=1e5+5;
19 const int mod=1e9+7;
20 typedef __int64 ll;
21 typedef struct
22 {
23     int val,pos;
24 }aa;
25 aa a[maxn];
26 int l[maxn],r[maxn];
27 vector<int> v[10005];//保存每个数i的因子的在a[]数组里的下标
28 bool cmp(aa x,aa y)
29 {
30     if(x.val==y.val)//注意如果有相同的数,优先前面的,为了找到最近的因子
31         return x.pos<y.pos;
32     return x.val<y.val;
33 }
34 int main()
35 {
36     int n;
37     while(~scanf("%d",&n))
38     {
39         ll ans=0;
40         for(int i=1;i<=n;i++)
41             scanf("%d",&a[i].val),a[i].pos=i;
42         for(int i=1;i<=10005;i++) v[i].clear();
43         for(int i=1;i<=n;i++)
44             l[i]=0,r[i]=n+1;
45         //用结构体存了下标对应的数,排序是为找因子
46         //每个数的因子一定小于等于它,因子先出现放在前面;
47         //当考虑到一个数的时候,它的因子已经全部找出来了
48         sort(a,a+n,cmp);
49         for(int i=1;i<=n;i++)
50         {
51             int tmp=a[i].val;
52             for(int j=tmp;j<=10000;j+=tmp)//添加因子,数不多
53                 v[j].push_back(a[i].pos);
54         }
55         for(int i=1;i<=n;i++)
56         {
57             int tmp=a[i].val;
58             for(int j=v[tmp].size()-1;j>=0;j--)//暴搜所有因子的位置,找最近的
59             {
60                 if(v[tmp][j]<a[i].pos) l[a[i].pos]=max(l[a[i].pos],v[tmp][j]);
61                 if(v[tmp][j]>a[i].pos) r[a[i].pos]=min(r[a[i].pos],v[tmp][j]);
62             }
63         }
64         for(int i=1;i<=n;i++)
65         {
66             int t=a[i].pos;
67             ans=(ans+(ll)(a[i].pos-l[a[i].pos])*(r[a[i].pos]-a[i].pos))%mod;
68         }
69         printf("%I64d\n",ans);
70     }
71     return 0;
72 }

时间: 2024-08-01 06:34:46

hdu 5288 OO’s Sequence的相关文章

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

HDU 5288 OO&#39;s sequence (2015多校第一场 二分查找)

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

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

题目链接: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): 985    Accepted Submission(s): 375 Problem Description OO has got a array

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(多校第一场1001)

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

HDU 5288 OO’s Sequence(数学啊 多校2015)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5288 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 kn

hdu 5288 OO’s Sequence(2015多校第一场第1题)枚举因子

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5288 题意:在闭区间[l,r]内有一个数a[i],a[i]不能整除 除去自身以外的其他的数,f(l,r)表示在这区间内a[i]这样的数的个数,,现给你n个数,求所有区间的f(l,r)的和. 思路:对于每个数a[i]求出他的左右侧最靠近他的且是他的因子的位置L.R,并记录,那么对于每个数a[i]都有了他的L,R,而对于每个a[i]在f(l,r)有价值的次数之和就是(i-L+1)*(R-i+1) 代码:

hdu 5288 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 mul