题解 P7273 【ix35 的等差数列】

O(w√n) 的随机化做法

显然可以发现,构造出的等差数列,至少包含原数列的其中一项。

那么可以先枚举一个固定的公差,枚举原数列的其中几项,来构造等差数列。但是要枚举哪几项呢?随机枚举!!!

在比赛中我枚举了 \(7\sqrt n\) 项A了,但如果要保证正确性应该差不多 \(20\sqrt n\)

复杂度分析:从 \(0\sim \dfrac{w}{n-1}\) 枚举公差,再枚举 \(\sqrt n\) 项然后 \(\mathcal O(n)\) 计算答案,应为 \(\mathcal O(\dfrac{w}{n}\times n\sqrt n)=\mathcal O(w\sqrt n)\),足以通过此题。

Code

#include<bits/stdc++.h>
using namespace std;
#define il inline
#define ll long long
#define TT template<typename T>
namespace io{...}using namespace io;
const int N=3e5+5;
int n,w,a[N],ans=N;
int main(){
   srand(19491001);
   n=read();w=read();
   int tot=sqrt(n)*20;
   if(n<=2)return puts("0"),0;
   for(int i=1;i<=n;i++)
       a[i]=read();
   for(int d=0;d<=3e5;d++){
       if(1ll*d*(n-1)>=1ll*w)break;//当极差大于w
       for(int t=1;t<=tot;t++){
           int p=rand()%n+1,res=0;
           ll st=a[p]-1ll*(p-1)*d,ed=a[p]+1ll*(n-p)*d;//计算首末项
           if(st<=0||ed>w)continue;
           for(int i=1;i<p;i++,st+=d)
               if(a[i]!=st)res++;
           for(int i=n;i>p;i--,ed-=d)
               if(a[i]!=ed)res++;
           //计算答案
           ans=min(ans,res);
       }
   }writeln(ans);
   return 0;
}

比赛唯一过掉的题QAQ

posted @ 2021-01-16 23:40  ADay526  阅读(167)  评论(1)    收藏  举报