HDU - 5288-OO’s Sequence-数学+分类再二分+枚举+contribution costing
2016-04-02 17:03
411 查看
http://acm.hdu.edu.cn/showproblem.php?pid=5288
题意:
对一个区间【l,r】,我们看有多少个ai,满足ai%区间内任何数(除了ai) 都不为零,也即整除
如果有x个ai,则这个区间的贡献为x
给n个数数组,求所有区间的贡献和。
思路:直接求每个区间的贡献并不好求,我们可以转化为【求每个数ai对答案的贡献】。
对ai,我们找到分别在左边和右边离ai最近的一个因子y1,y2
那么显然在【y1+1,y2-1】内的所有包含ai的区间里,ai都满足 【不能整除区间内任何数】
这个数就是 (i-y1) * (y2-i);
那么答案只要累计每个数ai的贡献便可
那么我们怎么求离ai左右最近的因子呢, 先把所有数a[i]存到一个vector【a[i]】(下标升序)
那么每次对ai处理时,我们先枚举ai的所有因子j
然后在vector【j】里二分查找并更新【离ai左右最近的因子的位置】
因此复杂度是n*sqrt(n)* 【k】 (因为vector里面的数一般都是很少的,所以这个查找近乎为常数的量级
题意:
对一个区间【l,r】,我们看有多少个ai,满足ai%区间内任何数(除了ai) 都不为零,也即整除
如果有x个ai,则这个区间的贡献为x
给n个数数组,求所有区间的贡献和。
思路:直接求每个区间的贡献并不好求,我们可以转化为【求每个数ai对答案的贡献】。
对ai,我们找到分别在左边和右边离ai最近的一个因子y1,y2
那么显然在【y1+1,y2-1】内的所有包含ai的区间里,ai都满足 【不能整除区间内任何数】
这个数就是 (i-y1) * (y2-i);
那么答案只要累计每个数ai的贡献便可
那么我们怎么求离ai左右最近的因子呢, 先把所有数a[i]存到一个vector【a[i]】(下标升序)
那么每次对ai处理时,我们先枚举ai的所有因子j
然后在vector【j】里二分查找并更新【离ai左右最近的因子的位置】
因此复杂度是n*sqrt(n)* 【k】 (因为vector里面的数一般都是很少的,所以这个查找近乎为常数的量级
#include <cstdio> #include <cmath> #include <cstring> #include <string> #include <algorithm> #include <queue> #include <map> #include <set> #include <vector> #include <iostream> using namespace std; const double pi=acos(-1.0); double eps=0.000001; __int64 min(__int64 a,__int64 b) {return a<b?a:b;} __int64 max(__int64 a,__int64 b) {return a>b?a:b;} int tm[100005]; vector<int>mp[10005],sb; //hash __int64 mod=1e9+7; int main() { int n,i,j; while(scanf("%d",&n)!=EOF) { for (i=1;i<=10005;i++) mp[i].clear(); for (i=1;i<=n;i++) { scanf("%d",&tm[i]); mp[tm[i]].push_back(i); } __int64 ans=0; for (i=1;i<=n;i++) { __int64 minn=0; __int64 maxx=n+1; for (j=1;j*j<=tm[i];j++) //枚举因子 { if (tm[i]%j==0) { int tmp=j; int it=upper_bound(mp[tmp].begin(),mp[tmp].end(),i)-mp[tmp].begin(); //二分找到第一个在i右边的值 if (it!=mp[tmp].size()) maxx=min(maxx,mp[tmp][it]); it=lower_bound(mp[tmp].begin(),mp[tmp].end(),i)-mp[tmp].begin(); //二分找到第一个在i左边的值 it--; if (it>=0) minn=max(minn,mp[tmp][it]); if (j==tm[i]/j)continue; tmp=tm[i]/j; it=upper_bound(mp[tmp].begin(),mp[tmp].end(),i)-mp[tmp].begin(); if (it!=mp[tmp].size()) maxx=min(maxx,mp[tmp][it]); it=lower_bound(mp[tmp].begin(),mp[tmp].end(),i)-mp[tmp].begin(); it--; if (it>=0) minn=max(minn,mp[tmp][it]); } } ans+=(maxx-i)*(i-minn)%mod; //累加tm[i]的贡献 ans%=mod; } printf("%I64d\n",ans%mod); } return 0; }
相关文章推荐
- [LeetCode]Implement Stack using Queues
- JS/html/form/XMLHttpRequest Ajax 批量上传文件/图片的3种方式
- POJ1679 The Unique MST
- <%@ include file=” ”%> 和<jsp:include page=” ” flush=”true”/> 区别
- Unique Binary Search Trees
- UITableView的优化
- leetcode 300. Longest Increasing Subsequence 最长上升序列数
- LeetCode334. Increasing Triplet Subsequence
- easyui tree文本单击事件切换展开/折叠节点的状态
- Android多国语言的value文件夹命名方式
- AndroidUI组件之ActionBar--基于下拉的导航方式
- requirejs的使用
- 60. Permutation Sequence
- 这么巧妙思路(二)Longest Ordered Subsequence
- 232. Implement Queue using Stacks
- String,StringBuffer与StringBuilder的区别??
- 免安裝、免設定的 Hadoop 開發環境 - cloudera 的 QuickStart VM
- 最长公共子序列问题 POJ 1458 Common Subsequence
- 这么巧妙的思路Common Subsequence
- Xcode的Architectures、Valid Architectures和Build Active Architecture Only属性