hdu 5381 The sum of gcd 原来有个算法叫莫队 2015 Multi-University Training Contest 8
2015-08-17 19:33
585 查看
The sum of gcd
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 659 Accepted Submission(s): 279
Problem Description
You have an array A,the
length of A is n
Let f(l,r)=∑ri=l∑rj=igcd(ai,ai+1....aj)
Input
There are multiple test cases. The first line of input contains an integer T, indicating the number of test cases. For each test case:
First line has one integers n
Second line has n integers Ai
Third line has one integers Q,the
number of questions
Next there are Q lines,each line has two integers l,r
1≤T≤3
1≤n,Q≤104
1≤ai≤109
1≤l<r≤n
Output
For each question,you need to print f(l,r)
Sample Input
2 5 1 2 3 4 5 3 1 3 2 3 1 4 4 4 2 6 9 3 1 3 2 4 2 3
Sample Output
9 6 16 18 23 10
Author
SXYZ
Source
2015 Multi-University Training Contest 8
Recommend
wange2014 | We have carefully selected several similar problems for you: 5395 5394 5393 5392 5391
预处理是必须的。
莫队算法,先将n个数以长度为sqrt(n)进行划分,
对于每一个数,他与其它数gcd后的结果最多有32种(2^32 = 4 294 967 296),
以不同的值所在区域为标准储存,预处理以x为ri,以x为le 的区间gcd和,node R[x][最多32个] {int le, ri;LL gcd;}(并用结构体记录位置,)
将查询排序,以le所属块编号在前面的排在前,若块相同,ri小的在前。
莫队算法的思想是,两个相邻的查询x1,x2之间,用x1的结果加减乘除得到x2的结果,而且是一个数一个数的移动。
什么意思?就是假如x1:( 3,5 ) ,x2(3 ,7),那么计算玩x1(3,5)后,再计算(3,6),再计算(3,7),两个计算。
如果是x1(3,5) ,x2(4,7),那么x1(3,5)->(4,5)->(4,6)->x2(4,7);
假如按照上面的排序了,那么在每一块中,最多移动n+sqrt(n)次(约等于n),每一移动一次最多32次计算找到对应位置的gcd,有sqrt(n)块查询。
所以总的复杂度大约是O(n*sqrt(n) *32); (o( n^1.5 *32 ) )
(PS;预处理R[x][]的时候可以利用前面一个数的结论,若是得到R,(以x为ri)从1开始到n (因为要向左找),若是得到L,从n到1)。
#include<cstdio> #include<string> #include<cstring> #include<iostream> #include<cmath> #include<algorithm> #include<climits> #include<queue> #include<vector> #include<map> #include<sstream> #include<set> #include<stack> #include<utility> #pragma comment(linker, "/STACK:102400000,102400000") #define PI 3.1415926535897932384626 #define eps 1e-10 #define sqr(x) ((x)*(x)) #define FOR0(i,n) for(int i=0 ;i<(n) ;i++) #define FOR1(i,n) for(int i=1 ;i<=(n) ;i++) #define FORD(i,n) for(int i=(n) ;i>=0 ;i--) #define lson num<<1,le,mid #define rson num<<1|1,mid+1,ri #define MID int mid=(le+ri)>>1 #define zero(x)((x>0? x:-x)<1e-15) using namespace std; const int INF =0x3f3f3f3f; const int maxn= 10000+10 ; //const int maxm= ; //const int INF= ; typedef long long ll; const ll inf =1000000000000000;//1e15; //ifstream fin("input.txt"); //ofstream fout("output.txt"); //fin.close(); //fout.close(); //freopen("a.in","r",stdin); //freopen("a.out","w",stdout); //by yskysker123 int a[maxn]; int n,m,block; struct Que { int le,ri,pos; ll ans; }que[maxn]; struct Ansblock { int le,ri; ll gcd; Ansblock(){} Ansblock(int l,int r,ll gc):le(l),ri(r),gcd(gc){ } } ; vector<Ansblock>L[maxn],R[maxn]; inline bool cmp(Que x,Que y) { if( x.pos/block==y.pos/block) return x.ri<y.ri; return x.le<y.le; } inline bool cmp2(Que x,Que y) { return x.pos<y.pos; } void Pre() { L .push_back( Ansblock( n,n,a ) ); for(int i=n-1;i>=1;i--) { int le=i,ri=i; ll gcd=a[i]; int tmp; for(int j=0;j<L[i+1].size();j++) { int tmp= __gcd( gcd,L[i+1][j].gcd ); if( gcd!= tmp ) { L[i].push_back( Ansblock( le,ri,gcd ) ); gcd=tmp; le=ri+1; } ri=L[i+1][j].ri; } L[i].push_back(Ansblock( le,ri,gcd ) ); } R[1].push_back(Ansblock( 1,1,a[1] ) ); for(int i=2;i<=n;i++) { int le=i,ri=i; ll gcd=a[i]; int tmp; for(int j=0;j<R[i-1].size();j++) { int tmp=__gcd(gcd,R[i-1][j].gcd); if(gcd!=tmp) { R[i].push_back(Ansblock( le,ri,gcd ) ); gcd=tmp; ri=le-1; } le=R[i-1][j].le; } R[i].push_back( Ansblock(le,ri,gcd ) ); } } ll queryR(int le,int ri) { ll ans=0; int x=le; for(int i=0;i<R[ri].size();i++) { if( R[ri][i].le <= x && x<= R[ri][i].ri ) { ans+=R[ri][i].gcd *( R[ri][i].ri-x+1 ); return ans; } ans +=(R[ri][i].ri-R[ri][i].le+1)*R[ri][i].gcd; } } ll queryL(int le,int ri) { ll ans=0; int x=ri; for(int i=0;i<L[le].size() ;i++) { if(L[le][i].le<=x&&x<=L[le][i].ri) { ans+=L[le][i].gcd*( x-L[le][i].le+1 ); return ans; } ans+=(L[le][i].ri-L[le][i].le+1)*L[le][i].gcd; } } void Cal() { sort(que+1,que+1+m,cmp); ll ans=0; int le=1,ri=0; for(int i=1;i<=m;i++) { for( ;ri<que[i].ri ;ri++ ) ans+=queryR( le,ri+1); for( ;ri>que[i].ri ;ri-- ) ans-=queryR(le,ri); for( ;le>que[i].le;le-- ) ans+=queryL( le-1,ri ); for( ;le<que[i].le;le++ ) ans-=queryL(le, ri); que[i].ans=ans; } sort(que+1,que+1+m,cmp2); for(int i=1;i<=m;i++) { printf("%lld\n",que[i].ans); } } int main() { int T;scanf("%d",&T); while(T--) { scanf("%d",&n); FOR1(i,n) { L[i].clear(); R[i].clear(); scanf("%d",&a[i]); } scanf("%d",&m); FOR1(i,m) { scanf("%d%d",&que[i].le,&que[i].ri); que[i].pos=i; } block=sqrt(n); Pre(); Cal(); } return 0; } /* 2 5 1 2 3 4 5 3 1 3 2 3 1 4 */
ps: 此代码 hdu 上 G++ 大约800ms到1000+ ms,可能会超时。
相关文章推荐
- 1079. Total Sales of Supply Chain (25)
- PAT 1086. Tree Traversals Again (25)
- Hive的Explain命令
- How To run OAI eNB (No S1) with USRP X310(1)
- pywin32 ImportError: DLL load failed: 找不到指定的模块
- 关于百度地图开发中可能遇到Conversion to Dalvik format failed with error 1
- 2015 Multi-University Training Contest 8 hdu 5381 The sum of gcd
- atomic和nonatomic assign retain
- HDOJ 4460 Friend Chains 图的最长路
- 2015 Multi-University Training Contest 8(HDOJ5384、5389)
- 2015 Multi-University Training Contest 8
- Testng 运行报错:"Total tests run: 0, Failures: 0, Skips: 0"以及找不到class文件的问题
- [观察]HDOJ1021Fibonacci Again
- 2015 HUAS Summer Trainning #6~G
- 关于hp proliant sl210t服务器raid 1阵列配置
- Agent admitted failure to sign using the key
- retain(strong)和copy之间的关系
- Air Raid
- 基于QMainWindow的主窗口程序例子
- 70 Climbing Stairs