莫比乌斯反演 hdu 4676 Sum Of Gcd
来源:互联网 发布:淘宝月销量怎么算 编辑:程序博客网 时间:2024/04/29 09:43
Sum Of Gcd
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others)Total Submission(s): 513 Accepted Submission(s): 222
Problem Description
Given you a sequence of number a1, a2, ..., an, which is a permutation of 1...n.
You need to answer some queries, each with the following format:
Give you two numbers L, R, you should calculate sum of gcd(a[i], a[j]) for every L <= i < j <= R.
You need to answer some queries, each with the following format:
Give you two numbers L, R, you should calculate sum of gcd(a[i], a[j]) for every L <= i < j <= R.
Input
First line contains a number T(T <= 10),denote the number of test cases.
Then follow T test cases.
For each test cases,the first line contains a number n(1<=n<= 20000).
The second line contains n number a1,a2,...,an.
The third line contains a number Q(1<=Q<=20000) denoting the number of queries.
Then Q lines follows,each lines contains two integer L,R(1<=L<=R<=n),denote a query.
Then follow T test cases.
For each test cases,the first line contains a number n(1<=n<= 20000).
The second line contains n number a1,a2,...,an.
The third line contains a number Q(1<=Q<=20000) denoting the number of queries.
Then Q lines follows,each lines contains two integer L,R(1<=L<=R<=n),denote a query.
Output
For each case, first you should print "Case #x:", where x indicates the case number between 1 and T.
Then for each query print the answer in one line.
Then for each query print the answer in one line.
Sample Input
153 2 5 4 131 52 43 3
Sample Output
Case #1:1140
Source
2013 Multi-University Training Contest 8
题意:有一个数列,是1~n的排列。然后有Q个询问,询问[L,R]中所有gcd(a[i],a[j]) i<j 之和。
思路:
代码:
#include <iostream>#include <cstdio>#include <string.h>#include <cstring>#include <vector>#include <cmath>#include <algorithm>#include <queue>using namespace std;#define LL long long#define clr(a,x) memset(a,x,sizeof(a))#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1#define mp make_pair#define Fout(file) freopen(file,"w",stdout)#define Fin(file) freopen(file,"r",stdin)const int maxn=20000+5;int n,Q;struct Point{ int x,y,id; Point(int x=0,int y=0,int id=0) :x(x),y(y),id(id) { } bool operator<(const Point&a) const { if(a.x==x) return y>a.y; return x<a.x; }}pt[maxn],cpy[maxn];struct SegmentTree{ int minimal[maxn<<2],id[maxn<<2]; int tree_size; void PushUp(int rt) { if(minimal[rt<<1]>minimal[rt<<1|1]) minimal[rt]=minimal[rt<<1|1],id[rt]=id[rt<<1|1]; else minimal[rt]=minimal[rt<<1],id[rt]=id[rt<<1]; } void init() { clr(minimal,0x3f); clr(id,-1); } void update(int p,int x,int id) { p+=tree_size; if(minimal[p]<=x) return; minimal[p]=x; this->id[p]=id; p>>=1; while(p>=1) { PushUp(p); p>>=1; } } int query(int l,int r) { l+=tree_size; r+=tree_size; int ret=-1; while(l<=r) { if(l&1) { if(id[l]!=-1) { if(ret==-1) ret=id[l]; else if(pt[ret].x+pt[ret].y>pt[id[l]].x+pt[id[l]].y) ret=id[l]; } ++l; } if(~r&1) { if(id[r]!=-1) { if(ret==-1) ret=id[r]; else if(pt[ret].x+pt[ret].y>pt[id[r]].x+pt[id[r]].y) ret=id[r]; } --r; } l>>=1; r>>=1; } return ret; }}segtree;struct Edge{ int u,v,cost; Edge(int u=0,int v=0,int cost=0) :u(u),v(v),cost(cost) { } bool operator<(const Edge&e) const { return cost<e.cost; }}edges[maxn<<3];int e_cnt;struct Node{ int v; Node *next;}*first[maxn],edge[maxn<<1];int ptr;void add(int u,int v){ edge[++ptr].v=v; edge[ptr].next=first[u]; first[u]=&edge[ptr];}int a[maxn],b[maxn];bool cmp_a(int x,int y) { return a[x]<a[y]; }int Bin(int x,int l,int r){ int m; while(l<=r) { m=(l+r)>>1; if(a[b[m]]==x) return m; else if(a[b[m]]<x) l=m+1; else r=m-1; } return l;}int find(int x){ if(x==b[x]) return x; return b[x]=find(b[x]);}void swap(int&a,int&b) { a^=b; b^=a; a^=b; }void MST(int n){ e_cnt=0; for(int dir=0;dir<4;++dir) { if(dir==1||dir==3) for(int i=0;i<n;++i) swap(pt[i].x,pt[i].y); else if(dir==2) for(int i=0;i<n;++i) pt[i].x=-pt[i].x; sort(pt,pt+n); segtree.init(); for(int i=0;i<n;++i) a[i]=pt[i].y-pt[i].x,b[i]=i; sort(b,b+n,cmp_a); int c=1; for(int i=1;i<n;++i) if(a[b[i]]!=a[b[i-1]]) b[c++]=b[i]; int & sz=segtree.tree_size; sz=1; while(sz<c) sz<<=1; --sz; for(int i=n-1;i>=0;--i) { int h=Bin(pt[i].y-pt[i].x,0,c-1)+1; int x=segtree.query(h,c); if(x!=-1) edges[e_cnt++]=Edge(pt[i].id,pt[x].id,pt[x].y+pt[x].x-pt[i].x-pt[i].y); segtree.update(h,pt[i].x+pt[i].y,i); } } sort(edges,edges+e_cnt); for(int i=0;i<n;++i) b[i]=i; clr(first,0); ptr=0; int len=0; int rest=n-1; for(int i=0;i<e_cnt;++i) { Edge&e=edges[i]; if(find(e.u)==find(e.v)) continue; b[find(e.u)]=find(e.v); add(e.u,e.v); add(e.v,e.u); len+=e.cost; if(--rest==0) break; }}LL u[maxn],w[maxn];int factor[maxn][85],sz[maxn];void divide_factor(int x){ sz[x]=0; for(LL i=1;i*i<=x;++i) { if(x%i) continue; factor[x][sz[x]++]=x/i; if(i!=x/i) factor[x][sz[x]++]=i; }}int cal_mu(int x){ int odd=1; for(LL i=2;i*i<=x;++i) { int cnt=0; while(x%i==0) { x/=i; ++cnt; } if(cnt>1) return 0; else if(cnt==1) odd=-odd; } if(x>1) odd=-odd; return odd;}void pre_init(){ u[1]=1; factor[1][0]=1; sz[1]=1; for(int i=2;i<=20000;++i) { divide_factor(i); u[i]=cal_mu(i); } for(int i=1;i<=20000;++i) { w[i]=0; for(int j=0;j<sz[i];++j) { w[i]+=u[factor[i][j]]*i/factor[i][j]; } }}int val[maxn];char ch;void read_int(int & x){ ch=getchar(); x=0; while(ch<'0'||ch>'9') ch=getchar(); while('0'<=ch&&ch<='9') x=10*x+ch-'0',ch=getchar();}LL num[maxn];LL ans;LL output[maxn];void update(int x,LL sign){ for(int i=0;i<sz[x];++i) { int y=factor[x][i]; ans=ans+sign*num[y]*w[y]; if(sign<0) ans+=w[y]; num[y]+=sign; }}void input(){ scanf("%d",&n); for(int i=0;i<n;++i) read_int(val[i]); scanf("%d",&Q); for(int i=0;i<Q;++i) { read_int(pt[i].x); read_int(pt[i].y); pt[i].id=i; cpy[i]=pt[i]; --cpy[i].x; --cpy[i].y; }}void dfs(int id,int l,int r,int fa){ int L=pt[id].x,R=pt[id].y; int l0=l,r0=r; while(r0<R) { ++r0; update(val[r0],1); } while(r0>R) { update(val[r0],-1); --r0; } while(l0>L) { --l0; update(val[l0],1); } while(l0<L) { update(val[l0],-1); ++l0; } output[id]=ans; for(Node*p=first[id];p;p=p->next) { int nxt=p->v; if(nxt==fa) continue; dfs(nxt,l0,r0,id); } while(r0<r) { ++r0; update(val[r0],1); } while(r0>r) { update(val[r0],-1); --r0; } while(l0>l) { --l0; update(val[l0],1); } while(l0<l) { update(val[l0],-1); ++l0; }}void solve(){ for(int i=0;i<Q;++i) pt[i]=cpy[i]; dfs(0,pt[0].x,pt[0].x-1,-1); for(int i=0;i<Q;++i) printf("%I64d\n",output[i]);}int main(){ pre_init(); int T;cin>>T; for(int Cas=1;Cas<=T;++Cas) { ans=0; input(); MST(Q); printf("Case #%d:\n",Cas); solve(); }}
0 0
- 莫比乌斯反演 hdu 4676 Sum Of Gcd
- HDU 4676 Sum Of Gcd(莫队+莫比乌斯反演)
- [数论][莫队][莫比乌斯反演] hdu 4676 Sum Of Gcd
- [莫比乌斯反演+莫队] HDU4676 Sum Of Gcd
- [反演 莫队算法] HDU 4676 Sum Of Gcd
- ACdream 1148 GCD SUM 莫比乌斯反演
- HDU 4675 GCD of Sequence (莫比乌斯反演)
- HDU 4675-GCD of Sequence(莫比乌斯反演+组合数+逆元)
- hdu 4947 GCD Array 莫比乌斯反演
- HDU-1695-GCD(莫比乌斯反演)
- hdu 1695 GCD(莫比乌斯反演)
- hdu 1695 GCD 莫比乌斯反演
- HDU 1695 GCD(莫比乌斯反演)
- HDU 1695 GCD(莫比乌斯反演)
- HDU 1695 GCD【莫比乌斯反演】
- HDU 1695 GCD [莫比乌斯反演]
- HDU 1695 GCD(莫比乌斯反演)
- HDU 1695 GCD (莫比乌斯反演)
- 环境变量设置
- poj 1837 Balance (0 1 背包)
- 暑期没有WiFi怎么过?
- JavaScript HTML DOM
- ORACLE分页SQL语句
- 莫比乌斯反演 hdu 4676 Sum Of Gcd
- 全民免费wifi斗法中
- Execl表格列数据筛选及替换!
- 整合CKEditor和CKFinder(for java)
- 通知
- 第三周总结
- dfsgfdhdgjh
- 总结LocalSessionFactoryBean加载Hibernate映射方式
- Activity透明/半透明效果的设置transparent(两种实现方法)