2016 Multi-University Training Contest 1 T4

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

求不修改区间gcd可以用线段树或者倍增。

求l-n的我们注意观察gcd(al​​,al+1​​,...,ar​​),当l固定不动的时候,r=l...n时,我们可以容易的发现,随着r的増大,gcd(al​​,al+1​​,...,ar​​)是递减的,同时gcd(al​​,al+1​​,...,ar​​)最多 有log 1000,000,000个不同的值,因为al​​最多也就有log 1000,000,000个质因数。

然后我们用链表记录所有gcd改变的点,这些点将l...n这一段分成若干个相同gcd的区间。由l...n的gcd关系可以推出l-1...n的gcd关系。相邻区间gcd相同时将两个区间合并。用map统计gcd是x的区间有多少个。

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<map>
  4 #define N 100010
  5 #define mem(a) memset(a,0,sizeof(a))
  6 using namespace std;
  7 int te,l[N*4],r[N*4],a[N*4],f[N],x[N];
  8 long long j,n,nex[N];
  9 int t,m,ans,ll,rr,num,i,_;
 10 map<int,long long> sc;
 11 
 12 int gcd(int aa,int bb)
 13 {
 14     int tt,a=aa,b=bb;
 15     while (a%b!=0)
 16     {
 17         tt=a;
 18         a=b;
 19         b=tt%b;
 20     }
 21     return b;    
 22 }
 23 void build(int s,int ll,int rr)
 24 {
 25     l[s]=ll;r[s]=rr;
 26     if (ll==rr)  
 27     {
 28         scanf("%d",&x[++num]);
 29         a[s]=x[num];
 30     }
 31     else
 32     {
 33         build(s*2,ll,(ll+rr)/2);
 34         build(s*2+1,(ll+rr)/2+1,rr);
 35         a[s]=gcd(a[s*2],a[s*2+1]);
 36     }
 37 }
 38 void sea(int s)
 39 {
 40     if (l[s]>rr || r[s]<ll) return;
 41     if (ll<=l[s] && rr>=r[s])
 42         if (ans==-1)
 43             ans=a[s];
 44         else
 45             ans=gcd(ans,a[s]);
 46     else
 47     {
 48         sea(s*2);
 49         sea(s*2+1);
 50     }
 51 }
 52 int main()
 53 {
 54     scanf("%d",&_);
 55     while (_--)
 56     {
 57         printf("Case #%d:\n",++te);
 58         num=0;
 59         mem(f);sc.clear();mem(nex);mem(l);mem(r);mem(a);
 60         scanf("%d",&n);
 61         build(1,1,n);
 62         f[n]=x[n];sc[x[n]]++;
 63         for (i=n-1;i>=1;i--)
 64         {
 65             j=i+1;
 66             while (j!=0)
 67             {
 68                 f[j]=gcd(f[j],x[i]);
 69                 j=nex[j];
 70             }
 71             f[i]=x[i];
 72             nex[i]=i+1;
 73             j=i;
 74             while (nex[j]!=0)
 75             {
 76                 if (f[j]==f[nex[j]])
 77                     nex[j]=nex[nex[j]];
 78                 else
 79                     j=nex[j];
 80             }
 81             j=i;
 82             while (j!=0)
 83             {
 84                 if (nex[j]==0)
 85                     sc[f[j]]+=n-j+1;
 86                 else
 87                     sc[f[j]]+=nex[j]-j;
 88                 j=nex[j];
 89             }
 90             
 91         }
 92         scanf("%d",&m);
 93         for (t=1;t<=m;t++)
 94         {
 95             scanf("%d%d",&ll,&rr);
 96             ans=-1;
 97             sea(1);
 98             printf("%d %I64d\n",ans,sc[ans]);
 99         }          
100     }
101     return 0;
102 }
View Code
Run ID Submit Time Judge Status Pro.ID Exe.Time Exe.Memory Code Len. Language Author
17643445 2016-07-20 14:35:10 Accepted 5726 1950MS 14112K 1557B G++ lbz007
posted @ 2016-07-20 15:46  lbz007  阅读(246)  评论(0编辑  收藏  举报
Live2D