• 7.14T1


    一道题连打加调,断断续续写了11个小时才A掉,是真的心累,想出来的各种时间复杂度低的算法最后被一个O(n2logn)干掉了,其实过了也并没有很开心,毕竟10个小时打O(n),最高才55分,O(n2logn)打了半个小时就干到了WA95,一共也就一个多小时就A掉了,各种错,各种不知道为什么,且搞不到数据的WA,从昨天下午5点一直交到今天下午3点

    前面都是废话,我就是想吐吐苦水

    关于这道题,首先感谢secret同学强大的证明,那就先说一下关于这个证明,有用到一点求gcd,我不会太严格的证明,有质疑的,或者可以搞出反例的,欢迎diss我

    对于两个数x,y(保证较大数可以整除较小数),如果一直拿大数处以小数,留下小数和刚才的商继续除,一直除到两个相等的数,那最后这个数,一定是x,y共同的关于这个数的某次幂,且这个数是可以满足作为x,y的底数的最大数,其实这个除,就是在底数的幂上做gcd,只不过由于最初不知道底数,不能直接给指数gcd,所以利用整个数去除来实现这个过程,不懂的话,自己摆几个例子感性想一下吧,我能力不太够,可能讲不清楚

    有了这个东西我们就可以进入这道题了,首先作为一个高考生,应该想到,等比数列应该分为公比为一和公比不为一,为一的话O(n)扫一边肯定没问题,关键就是这个公比不为一的时候,我一直坚强的想要打O(n),一直没成功,结果最后的O(n2)跟他们O(n)一个时间,没A的方法就不多BB了,就说一下这个暴力的O(n2)

    既然要构成一个无序的等比数列,那就需要满足序列中每挨着的两个数之间的比值都是公比的几次幂,这个很显然了,不会的直接用等比数列的公式搞一搞,那问题就是找到这个公比,并且判断后面的数是否满足这个公比,满足一直向后推,不满足,更新答案跳出去,这个公比的求法就用到了我一开始说的那个证明,只不过他求得是最大的,而这个公比可能会不停被往小了的方向更新

    举个例子对于数列64 8 32 4 2,公比的变化是8,4,4,2

    通过这个方法以每个点为起点判就可以了

    关于可能会重复,set直接搞定就可以了

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<set>
     4 #define ll long long
     5 #define maxn 100100
     6 using namespace std;
     7 int n,i,tot,ans;
     8 ll gb;
     9 ll a[maxn],chu[maxn];
    10 set <ll> b1;
    11 ll CHU(ll x,ll y)
    12 {
    13     if(x<y)  swap(x,y);
    14     if(x%y)  return -1;
    15     ll ans=x/y;  return ans;
    16 }
    17 ll quary(ll x,ll y)
    18 {
    19     if(x==1||y==1)  return max(x,y);
    20     while(x!=y)
    21     {
    22         if(x<y)  swap(x,y);
    23         if(x%y)  return 0;
    24         ll da=x/y;
    25         x=y;  y=da;
    26     }
    27     return x;
    28 }
    29 int main()
    30 {
    31     scanf("%d",&n);
    32     for(int j=1;j<=n;++j)
    33     {
    34         scanf("%lld",&a[j]);
    35         if(j==1)  continue;
    36         chu[j]=CHU(a[j],a[j-1]);
    37     }
    38     for(int j=1;j<n;++j)
    39     {
    40         //cout<<"搜索"<<j<<endl;
    41         if(chu[j+1]==-1)  {/*cout<<"在chu[j+1]==-1处被干掉"<<endl;*/  continue;}
    42         b1.clear();  ans=2;  gb=chu[j+1];
    43         if(gb==0)  {/*cout<<"在gb==0处被干掉"<<endl;*/  continue;}
    44         b1.insert(a[j]);  b1.insert(a[j+1]);
    45         if(a[j]!=a[j+1])
    46         {
    47             for(int k=j+2;k<=n;++k)
    48             {
    49                 if(b1.count(a[k])!=0)  break;
    50                 if(chu[k]==-1)  break;
    51                 ll ls=quary(gb,chu[k]);
    52                 if(ls!=0)  {ans++;  b1.insert(a[k]);  gb=min(gb,ls);}
    53                 else  break;
    54             }
    55         }
    56         else
    57             for(int k=j+2;k<=n;++k)
    58             {
    59                 if(a[k]==a[j])  ans++;
    60                 else  break;
    61             }
    62         tot=max(tot,ans);
    63         //cout<<"从"<<j<<"起序列最长长度为"<<ans<<endl;
    64     }
    65     printf("%d
    ",tot);
    66     return 0;
    67 }
    View Code
  • 相关阅读:
    spring boot 配置时区差别
    Java 中序列化与反序列化引发的思考?
    Http 状态码总结
    Springboot
    ConcurrentHashMap 实现缓存类
    C#基础(二)拆箱与装箱,循环与选择结构,枚举
    C#基础知识(一)自己总结的。。。
    贪吃蛇大作战双人版加强版完整代码加详细步骤,不懂问博主 啦啦啦。
    C#数组随机生成四个随机数
    C#添加背景音乐
  • 原文地址:https://www.cnblogs.com/hzjuruo/p/11190058.html
Copyright © 2020-2023  润新知