题解 CF1654E Arithmetic Operations

容易发现,题意可以转化为:对于所有公差 k,把序列第 i 个数修改为 aii×k,最多有多少个相等的数。

|k|105 时,必然不可能相等。因此只要考虑 105<k<105 的情况。

考虑两个数距离为 dis 时,只有 dis×|k|105 才可能相等。因此,当 k 比较大的时候,每个数只可能和它后(前)面的 nk 个数相等。且如果 i 位置与 j 位置相等,k 是可以唯一确定的。

根号分治即可。取阈值为 lim,第一部分暴力枚举公差 O(lim×n),第二部分枚举第一个相等的数以及它后面 nk 个数,复杂度 O(n2lim)。所以当 lim=n,复杂度是 O(nn)。需要开 O(nn) 大小的桶记录。

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define mem(x) memset(x,0,sizeof(x))
#define printYes puts("Yes")
#define printYES puts("YES")
#define printNo puts("No")
#define printNO puts("NO")
#define lowbit(x) (x&(-x))

const ll inf=1000000000000000000; 
//const ll mod=998244353;
//const ll mod=1000000007;

const int N=100005,B=321,K=N*B+2*N;
int n,m,ans; 
int a[N];

int b[N*B*2+4*N],c[N];

inline int read()
{
    int F=1,ANS=0;
	char C=getchar();
    while (C<'0'||C>'9')
	{
		if (C=='-') F=-1;
		C=getchar();
	}
    while (C>='0'&&C<='9')
	{
		ANS=ANS*10+C-'0';
		C=getchar();
	}
    return F*ANS;
}

int main()
{
	n=read();
	for (int i=1;i<=n;i++) a[i]=read();
	for (int i=-B;i<=B;i++)
	{
		for (int j=1;j<=n;j++)
		{
			b[a[j]-i*j+K]++;
			ans=max(ans,b[a[j]-i*j+K]);
		}
		for (int j=1;j<=n;j++)
		{
			b[a[j]-i*j+K]--;
		}
	}
	for (int i=1;i<=n;i++)
	{
		int r=min(n,i+B);
		for (int j=i+1;j<=r;j++)
		{
			int det=a[j]-a[i],len=j-i;
			if (det%len!=0) continue;
			int k=det/len;
			b[k+K]++;
			ans=max(ans,b[k+K]+1);
		}
		for (int j=i+1;j<=r;j++)
		{
			int det=a[j]-a[i],len=j-i;
			if (det%len!=0) continue;
			int k=det/len;
			b[k+K]--;
		}
	}
	cout << n-ans;
	return 0;
}
posted @   Little09  阅读(40)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· AI与.NET技术实操系列(六):基于图像分类模型对图像进行分类
点击右上角即可分享
微信分享提示