Arithmetic Operations(CF 1654 E)

传送门

题目大意

给你一个序列,问最少的把一个数改成其他任意数的操作数使得这个序列变成一个等差数列。\((1\leq n\leq10^5,1\leq a_i\leq10^5)\)

思路

很容易就能想到把这个问题转化为一个二维平面上求一条直线能经过最多点的问题,但是由于纵坐标会很大,所以不能直接暴力枚举斜率,但是我们又能想到当斜率很大时,肯定不会有很多点被经过,所以对于小斜率我们可以直接暴力枚举,然后对于大斜率,我们两两之间进行枚举,然后就能轻松\(AC\)了。不过至于什么是小斜率,那就设的稍微小一点,\(20\)~\(50\)之间都行吧。

代码

#include<bits/stdc++.h>
using namespace std;
const int t=30;
int a[100005];
int main()
{
	int n;
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
		scanf("%d",&a[i]);
	int ans=0;
	for(int i=-t;i<=t;i++)
	{
		map<int,int>cnt;
		for(int j=1;j<=n;j++)
			ans=max(ans,++cnt[a[j]-i*j]);
	}
	for(int i=1;i<=n;i++)
	{
		map<int,int>cnt;
		int r=100000/t;
		for(int j=i+1;j-i<=r&&j<=n;j++)
		{
			int d=a[j]-a[i];
			if(d%(j-i))continue;
			d/=(j-i);
			ans=max(ans,++cnt[d]+1);
		}
	}
	printf("%d\n",n-ans);
	return 0;
}
posted @ 2022-03-22 09:36  Jerry_Black  阅读(83)  评论(0)    收藏  举报