HDU-6102 GCDispower(莫比乌斯函数+树状数组)
来源:互联网 发布:数控锥度编程 编辑:程序博客网 时间:2024/06/10 15:40
传送门:HDU-6102
题解:莫比乌斯函数+树状数组+离线操作
先对查询按R升序排序,从左到右枚举Ak,再枚举A1~Ak-1中Ak的倍数(因为是1~n的全排列,因此总枚举量为nlogn),得到B数组,将B数组中的数都除以Ak,并按照A中的下标从小到大排序,然后只要求B中所有GCD(Bi,Bj)==1(i<j)的二元组个数即可。
求二元组个数可以直接用莫比乌斯函数求得,对于Bi对答案的贡献为cnt[下标大于i且与Bi互质的Bj]*Ak
每次枚举Ak都要更新A1~Ak-1的贡献,因此可以用树状数组维护。总复杂度O(nlog^2n)
#include<bits/stdc++.h>#define FIN freopen("in.txt","r",stdin);using namespace std;typedef long long LL;typedef pair<int, int> PII;const int MX = 1e5 + 5;const int INF = 0x3f3f3f3f;struct Tree { int n; vector <LL> T ; void init (int sz) { T.clear(); n = sz; T.resize(n + 1); } void add (int x, LL v) { for (int i = x; i <= n; i += i & -i) T[i] += v; } LL sum (int x) { if (x > n) x = n; LL ret = 0; for (int i = x; i > 0; i -= i & -i) ret += T[i]; return ret; }} te;struct Query { int l, r, id; bool operator<(const Query& _A)const { if (r != _A.r) return r < _A.r; return l < _A.l; }} que[MX];struct Array { int val, index; bool operator<(const Array& _A)const { return index < _A.index; }} A[MX];int sz, vis[MX], arr[MX];bool prime[MX];int mob[MX], p[MX];vector<int> d[MX];int num[MX];void Mobius() { int pnum = 0; memset(prime, true, sizeof(prime)); mob[1] = 1; for(int i = 2; i < MX; i++) { if(prime[i]) { p[pnum ++] = i; mob[i] = -1; } for(int j = 0; j < pnum && (LL)i * p[j] < MX; j++) { prime[i * p[j]] = false; if(i % p[j] == 0) { mob[i * p[j]] = 0; break; } mob[i * p[j]] = -mob[i]; } }}void presolve() { for (int i = 1; i < MX; i++) { for (int j = i; j < MX; j += i) { d[j].push_back(i); } }}void solve(int k) { //A数组是Aj,B数组是Ai,i<j for (int i = 1; i <= sz; i++) { int t = A[i].val; for (int j = 0; j < d[t].size(); j++) num[d[t][j]]++; } for (int i = 1; i <= sz; i++) { LL cnt = 0; int t = A[i].val; for (int j = 0; j < d[t].size(); j++) num[d[t][j]]--; for (int j = 0; j < d[t].size(); j++) cnt += num[d[t][j]] * mob[d[t][j]]; te.add(A[i].index, cnt * k); }}LL ans[MX];int main() { //FIN; Mobius(); presolve(); int T, n, m; scanf("%d", &T); while (T--) { scanf("%d%d", &n, &m); te.init(n); for (int i = 1; i <= n; i++) { scanf("%d", &arr[i]); vis[i] = 0; } for (int i = 1; i <= m; i++) { scanf("%d%d", &que[i].l, &que[i].r); que[i].id = i; } sort(que + 1, que + m + 1); vis[arr[1]] = 1; vis[arr[2]] = 2; for (int i = 1, k = 3; i <= m; i++) { for (; k <= que[i].r; k++) { sz = 0; vis[arr[k]] = k; for (int x = 2; x * arr[k] <= n; x++) { if (vis[x * arr[k]]) { A[++sz].val = x; A[sz].index = vis[x * arr[k]]; } } sort(A + 1, A + sz + 1); solve(arr[k]); } ans[que[i].id] = te.sum(que[i].r) - te.sum(que[i].l - 1); } for (int i = 1; i <= m; i++) printf("%lld\n", ans[i]); } return 0;}
阅读全文
0 0
- HDU-6102 GCDispower(莫比乌斯函数+树状数组)
- HDU 6102 GCDispower(莫比乌斯反演)
- HDU 6102 GCDispower(容斥原理+数论+树状数组)
- hdu 6102 GCDispower 树状数组+容斥
- bzoj3529【线性筛】【莫比乌斯函数】【树状数组】
- 解题报告:HDU_6102 GCDispower (离线处理+莫比乌斯反演)
- HDU-4947-GCD Array(树状数组+莫比乌斯反演)
- HDU 5219 Repeating 后缀数组 + 莫比乌斯函数
- BZOJ3259(莫比乌斯反演 + 树状数组 + 离散处理 + 极性函数)
- [BZOJ3529][Sdoi2014]数表 && 莫比乌斯反演+树状数组
- [BZOJ3529]SDOI2014数表|莫比乌斯反演|树状数组
- 3529: [Sdoi2014]数表 莫比乌斯反演+树状数组
- 3529: [Sdoi2014]数表|莫比乌斯反演|树状数组
- 【bzoj3529】【SDOI2014】【数表】【莫比乌斯反演+树状数组】
- [BZOJ3529] [SDOI2014] 数表 - 莫比乌斯反演 - 树状数组
- BZOJ 3529 莫比乌斯反演+树状数组
- HDU4947(莫比乌斯反演 + 树状数组维护)
- bzoj3529 [Sdoi2014]数表(莫比乌斯反演+树状数组)
- 首页实现_头部广告页
- H5实现视频监控网络直播时前端自动适配
- 关于HDFS理解
- HDU 4923 Room and Moor【栈】【想法】
- SVM另讲
- HDU-6102 GCDispower(莫比乌斯函数+树状数组)
- day25(单例模式,多线程通信,线程组,线程状态,线程池,工厂模式)
- java克隆
- 解决安装php过程中出现的问题
- JavaScript 函数++
- PE安装及制作教程
- 表达式求值
- HDOJ 基础动归汇总 ,持续更新题目,一路打怪升级
- IDEA中Maven报错NoClassDefFoundError