HDU 5785 Function 倍增 (2016 ACM/ICPC Asia Regional Dalian Online)

Posted Coolxxx

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU 5785 Function 倍增 (2016 ACM/ICPC Asia Regional Dalian Online)相关的知识,希望对你有一定的参考价值。

Function

Time Limit: 7000/3500 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 976    Accepted Submission(s): 375


Problem Description
The shorter, the simpler. With this problem, you should be convinced of this truth.
  
  You are given an array A of N postive integers, and M queries in the form (l,r). A function F(l,r) (1lrN) is defined as:
F(l,r)={AlF(l,r1) modArl=r;l<r.
You job is to calculate F(l,r), for each query (l,r).
 

 

Input
There are multiple test cases.
  
  The first line of input contains a integer T, indicating number of test cases, and T test cases follow. 
  
  For each test case, the first line contains an integer N(1N100000).
  The second line contains N space-separated positive integers: A1,,AN (0Ai109).
  The third line contains an integer M denoting the number of queries. 
  The following M lines each contain two integers l,r (1lrN), representing a query.
 

 

Output
For each query(l,r), output F(l,r) on one line.
 

 

Sample Input
1 3 2 3 3 1 1 3
 

 

Sample Output
2
 

 

Source
 

 

Recommend
wange2014   |   We have carefully selected several similar problems for you:  5877 5872 5871 5870 5869 
 

 

Statistic | Submit | Discuss | Note

 

题目链接:

  http://acm.hdu.edu.cn/showproblem.php?pid=5875

题目大意:

  N个数(N<=100000),M个询问,每次询问L,R,求F(L,R)。

  F(L,R)=F(L,R-1)%A[R] , L<R

     =A[L] , L=R

题目思路:

  【倍增】

  这题数据水到暴力居然过了。。比赛的时候一想会T就没写。

  首先这题实际是求A[L]%A[L+1]%A[L+2]...%A[R]的值。

  那么很容易想到A[L]右边比他大的数都是没有必要取模的,变为找L右边第一个小于A[L]的取模

  模完后的结果缩小,再次寻找当前位置右边第一个小于此时的值的继续取模。可以证明这样的取模次数为log2N(100000取模后最大为49999)

  暴力的做法就是预处理的时候直接从后往前用单调栈求出位置X右边第一个小于A[X]的位置Y,next[X]=Y。查询的时候用next跳着模。

  当然这是不够的,因为可以构造出递减序列使得实际操作次数仍为N。

  用倍增的思想,对于位置i右侧的最长下降子序列,next[i][j]表示位置i右边第2j个的位置,预处理出每个位置的next数组

  每次做的时候尽量远跳,直到找到next[j][0]恰好小于当前的值z,则z对A[next[j][0]]取模,移动左标记,继续查找,直到超出R或者没有更小的数。

 

倍增:

技术分享
  1 //
  2 //by coolxxx
  3 //#include<bits/stdc++.h>
  4 #include<iostream>
  5 #include<algorithm>
  6 #include<string>
  7 #include<iomanip>
  8 #include<map>
  9 #include<stack>
 10 #include<queue>
 11 #include<set>
 12 #include<bitset>
 13 #include<memory.h>
 14 #include<time.h>
 15 #include<stdio.h>
 16 #include<stdlib.h>
 17 #include<string.h>
 18 //#include<stdbool.h>
 19 #include<math.h>
 20 #define min(a,b) ((a)<(b)?(a):(b))
 21 #define max(a,b) ((a)>(b)?(a):(b))
 22 #define abs(a) ((a)>0?(a):(-(a)))
 23 #define lowbit(a) (a&(-a))
 24 #define sqr(a) ((a)*(a))
 25 #define swap(a,b) ((a)^=(b),(b)^=(a),(a)^=(b))
 26 #define mem(a,b) memset(a,b,sizeof(a))
 27 #define eps (1e-10)
 28 #define J 10000
 29 #define mod 1000000007
 30 #define MAX 0x7f7f7f7f
 31 #define PI 3.14159265358979323
 32 #pragma comment(linker,"/STACK:1024000000,1024000000")
 33 #define N 100004
 34 #define M 18
 35 using namespace std;
 36 typedef long long LL;
 37 double anss;
 38 LL aans;
 39 int cas,cass;
 40 int n,m,lll,ans;
 41 int a[N],s[N];
 42 int nextt[N][M];
 43 void init()
 44 {
 45     int i,j,k,top;
 46     s[top=1]=n;
 47     for(i=0;i<M;i++)nextt[n][i]=n+1;
 48     for(i=n-1;i;i--)
 49     {
 50         while(top && a[i]<a[s[top]])top--;
 51         if(!top)nextt[i][0]=n+1;
 52         else nextt[i][0]=s[top];
 53         s[++top]=i;
 54     }
 55     for(j=1;j<M;j++)
 56     {
 57         for(i=1;i<n;i++)
 58         {
 59             k=nextt[i][j-1];
 60             nextt[i][j]=nextt[k][j-1];
 61         }
 62     }
 63 }
 64 int work(int l,int r)
 65 {
 66     int i,j,z=a[l];
 67     if(l==r)return z;
 68     while(l<r)
 69     {
 70         if(!z)return z;
 71         for(i=0;i<M-1;i++)
 72         {
 73             if(a[nextt[l][0]]<=z || nextt[l][i]>r)break;
 74             if(a[nextt[l][i+1]]<=z || nextt[l][i+1]>r)
 75             {
 76                 l=nextt[l][i];
 77                 i=-1;
 78                 continue;
 79             }
 80         }
 81         if(i==M || nextt[l][i]>r || !a[nextt[l][i]])return z;
 82         z%=a[nextt[l][0]];l=nextt[l][0];
 83     }
 84     return z;
 85 }
 86 int main()
 87 {
 88     #ifndef ONLINE_JUDGE
 89 //    freopen("1.txt","r",stdin);
 90 //    freopen("2.txt","w",stdout);
 91     #endif
 92     int i,j,k;
 93     int x,y,z;
 94 //    init();
 95     for(scanf("%d",&cass);cass;cass--)
 96 //    for(scanf("%d",&cas),cass=1;cass<=cas;cass++)
 97 //    while(~scanf("%s",s))
 98 //    while(~scanf("%d",&n))
 99     {
100         scanf("%d",&n);
101         for(i=1;i<=n;i++)scanf("%d",a+i);
102         init();
103         scanf("%d",&m);
104         for(i=1;i<=m;i++)
105         {
106             scanf("%d%d",&x,&y);
107             printf("%d\n",work(x,y));
108         }
109     }
110     return 0;
111 }
112 /*
113 //
114 
115 //
116 */
View Code

 

暴力:

技术分享
 1 //
 2 //by coolxxx
 3 //#include<bits/stdc++.h>
 4 #include<iostream>
 5 #include<algorithm>
 6 #include<string>
 7 #include<iomanip>
 8 #include<map>
 9 #include<stack>
10 #include<queue>
11 #include<set>
12 #include<bitset>
13 #include<memory.h>
14 #include<time.h>
15 #include<stdio.h>
16 #include<stdlib.h>
17 #include<string.h>
18 //#include<stdbool.h>
19 #include<math.h>
20 #define min(a,b) ((a)<(b)?(a):(b))
21 #define max(a,b) ((a)>(b)?(a):(b))
22 #define abs(a) ((a)>0?(a):(-(a)))
23 #define lowbit(a) (a&(-a))
24 #define sqr(a) ((a)*(a))
25 #define swap(a,b) ((a)^=(b),(b)^=(a),(a)^=(b))
26 #define mem(a,b) memset(a,b,sizeof(a))
27 #define eps (1e-10)
28 #define J 10000
29 #define mod 1000000007
30 #define MAX 0x7f7f7f7f
31 #define PI 3.14159265358979323
32 #pragma comment(linker,"/STACK:1024000000,1024000000")
33 #define N 100004
34 using namespace std;
35 typedef long long LL;
36 double anss;
37 LL aans;
38 int cas,cass;
39 int n,m,lll,ans;
40 int a[N],pre[N],s[N];
41 void print()
42 {
43     int i;
44     for(i=1;i<=n;i++)
45         printf("%d ",pre[i]);
46     puts("");
47 }
48 int main()
49 {
50     #ifndef ONLINE_JUDGE
51 //    freopen("1.txt","r",stdin);
52 //    freopen("2.txt","w",stdout);
53     #endif
54     int i,j,k;
55     int x,y,z,top,l,r;
56 //    init();
57     for(scanf("%d",&cass);cass;cass--)
58 //    for(scanf("%d",&cas),cass=1;cass<=cas;cass++)
59 //    while(~scanf("%s",s))
60 //    while(~scanf("%d",&n))
61     {
62         scanf("%d",&n);
63         for(i=1;i<=n;i++)
64         {
65             scanf("%d",&a[i]);
66         }
67         top=1;
68         s[top]=n;pre[n]=n+1;
69         for(i=n-1;i;i--)
70         {
71             while(top && a[i]<=a[s[top]])
72                 top--;
73             if(!top)pre[i]=n+1;
74             else pre[i]=s[top];
75             s[++top]=i;
76         }
77         scanf("%d",&m);
78         for(i=1;i<=m;i++)
79         {
80             scanf("%d%d",&l,&r);
81             x=a[l];
82             for(j=pre[l];j<=r;j=pre[j])
83                 x%=a[j];
84             printf("%d\n",x);
85         }
86         //print();
87     }
88     return 0;
89 }
90 /*
91 //
92 
93 //
94 */
View Code

 

  

以上是关于HDU 5785 Function 倍增 (2016 ACM/ICPC Asia Regional Dalian Online)的主要内容,如果未能解决你的问题,请参考以下文章

HDU - 5785:Interesting (回文树,求相邻双回文的乘积)

hdu 2586 How far away ?倍增LCA

HDU 6107 Typesetting 倍增

hdu 6107--Typesetting(倍增)

HDU 6107 Typesetting (倍增)

hdu2586 lca倍增法