hdu5288 区间个数
来源:互联网 发布:飞天网络 编辑:程序博客网 时间:2024/06/08 19:22
题意:给定一个n个数的序列,定义一个函数f(l, r),表示在[l, r]这个区间内,满足不是区间内任何其他数的倍数的数的个数。比如一个区间内的数为2,3,4,那么函数值为2。因为2和3都不是其他任何数的倍数,但4是2的倍数。现在要求所有的区间的函数值的和。
思路:相对于计算每个区间内有多少个这样的数,我们不如来看每个数被计算了多少次。每个数左面第一个不是他约数的数到右面第一个不是它约数的数,这样一个区间里的所有子区间 这个数都会被计算一次。设这个数的位置是pos,左右的那个位置分别是L,R,那么这个数被计算了(pos-L)*(R-pos)次。考虑到每个数最大也只有10000,不由得想到去预处理。首先预处理出1到10000每个数的约数,然后,对于数列里某个数,枚举它的所有约数(最多64个),用vector记录每个约数出现在哪些位置上(即下标),再二分找到左边最近的和右边最近的位置,更新离它最近的约数的位置即可。这样只有log(n)复杂度。
代码:
#include <cstdio> #include <iostream> #include <cstring> #include <string> #include <cmath> #include <algorithm> #include <stack> #include <vector> #include <map> #include <set> using namespace std; const int MAX = 1e5 + 5; const int MOD = 1e9 + 7; vector <int> yueshu[MAX], pos[MAX]; int n, a[MAX]; void initial() //预处理约数 { for(int i = 0; i < MAX; i++) yueshu[i].clear(); for(int i = 1; i <= 10000; i++) { for(int j = 1; j*j <= i; j++) { if(i%j == 0) { yueshu[i].push_back(j); if(j*j != i) yueshu[i].push_back(i/j); } } } } void input() { for(int i = 1; i <= n; i++) scanf("%d", &a[i]); } void solve() { for(int i = 0; i < MAX; i++) pos[i].clear(); for(int i = 1; i <= n; i++) //记录每个数出现的所有下标 pos[a[i]].push_back(i); long long ans = 0; for(int i = 1; i <= n; i++) { int maxl = 0, minr = n + 1; for(int j = 0; j < yueshu[a[i]].size(); j++) //枚举约数 { int temp = yueshu[a[i]][j]; if(pos[temp].size() == 0) continue; if(pos[temp][0] > i) { minr = min(minr, pos[temp][0]); continue; } if(pos[temp][pos[temp].size() - 1] < i) { maxl = max(maxl, pos[temp][pos[temp].size() - 1]); continue; } int l = 0, r = pos[temp].size() - 1, mid; while(l < r - 1) //二分找离a[i]左边和右边最近的当前约数 { mid = (l + r)/2; if(pos[temp][mid] < i) l = mid; else r = mid; } if(r + 1 < pos[temp].size()) //更新两边最近约数的位置 minr = min(minr, pos[temp][r + 1]); if(pos[temp][r] > i) minr = min(minr, pos[temp][r]); if(pos[temp][l] < i) maxl = max(maxl, pos[temp][l]); } ans = (ans + (long long)(i - maxl)*(minr - i))%MOD; } printf("%I64d\n", ans); } int main() { initial(); while(scanf("%d", &n) != EOF) { input(); solve(); } return 0; }
0 0
- hdu5288 区间个数
- hdu5288 区间求个数和
- hdu5288
- hdu5288
- HDU5288
- 重叠区间的个数
- 重叠区间个数
- 重叠区间的个数
- hdu5288 多校
- hdu5288 多校
- 求区间并的个数
- 区间内素数的个数
- 算法练习:重叠区间个数
- 重叠区间个数(算法)
- excel统计区间内个数
- 面试:数组:重叠区间个数
- 判断区间内素数个数
- 洛谷 p1865 区间质数个数
- Android四大组件之BroadcastReceiver
- Dubbo之旅--管理控制台(默认账户密码都是root)
- MapReduce初级案例
- 十进制转换为R进制
- mysql分页查询
- hdu5288 区间个数
- 初识Maven
- Spring 中 bean 之间的关系:parent(继承) 和 depends-on (依赖)作用是什么?
- MqSQL数据库的差集如何实现?Minus?
- Python学习笔记(二)
- Dubbo与Zookeeper、SpringMVC整合和使用(负载均衡、容错)
- MySQL 全文索引(fulltext)
- MySQL日期类型和毫秒值相互转换
- Android PreferenceFragment实现设置界面