zoukankan      html  css  js  c++  java
  • 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:
    ",++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
    ",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
    ------------------------------------------------------------------------- 花有重开日,人无再少年
  • 相关阅读:
    c#读取INI文件
    无题
    tnsping 命令解析
    宁静——一种心灵的奢望
    .NET框架类别
    19任意三个数的和为15
    VS.NET2005安装过程中遇到error:1935错误时的解决方法
    SQL Server 2005 : 存储过程传递字符串类型参数时,如何在参数中包含单引号
    SQL Server 2005 : 分割字符串
    网站发布在中文操作系统,但ReportViewer的工具栏显示为英文的解决方法
  • 原文地址:https://www.cnblogs.com/lbz007oi/p/5688604.html
Copyright © 2011-2022 走看看