CF1545D AquaMoon and Wrong Coordinate

Luogu 链接
CodeForces 链接
Virtual Judge 链接

题意

本题为 IO 交互题,请注意刷新缓冲区。


题目描述

在一条数轴的正半轴上有 \(n\) 个整点,它们会向正方向做匀速直线运动(速度大小为整数)。现在记录了它们 \(0\)\(T-1\) 的坐标集合(即顺序可能会被打乱),并有一个 \(t_0\)\(t_0\neq0\))时刻的坐标被修改了。

现在,你需要找出这一时刻 \(t_0\),以及被修改的坐标原本应该是什么。


交互格式

第一行两个正整数 \(n\)\(T\)\(5\le n\le1000\)\(7\le T\le1000\)),含意见题目描述
接下来 \(T\) 行每行 \(n\) 个正整数,代表点的坐标 \(x\)\(1\le x\le10^6\))。
保证 \(1\le v_i\le1000\)

输出仅一行,分别为 \(t_0\) 和修正后的坐标。

思路

记号

  • \(x_{t,i}\)\(t\) 时刻第 \(i\) 个点的坐标。
  • \(sum_{1,t}\)\(t\) 时刻 \(n\) 个点坐标之和。
  • \(sum_v\)\(n\) 个点的速度之和。
  • \(sum_{2,t}\)\(t\) 时刻 \(n\) 个点坐标的平方和。
  • \(sum_{v^2}\)\(n\) 个点速度的平方和。

找到 \(t_0\)

假设坐标未被修改,则对于任意 \(0<t<T\) 都有 \(\displaystyle sum_v=\sum_{i=1}^n v_i=sum_{1,t}-sum_{1,t-1}\)。因此,我们只需找到不相等的位置,就能找到 \(t_0\)

具体的,我们可以钦定 \(sum_v=sum_{1,1}-sum_{1,0}\),然后统计有多少与 \(sum_v\) 不相同,并记录第一个与 \(sum_v\) 不同的时刻 \(t_0\)
若有大于 \(2\) 个时刻与 \(sum_v\) 不相同,则将 \(t_0=1\),并将 \(sum_v\) 修改为 \(sum_{1,3}-sum_{1,2}\)

找到被修改的坐标

我们发现

\[\begin{aligned} sum_{2,t+1}-sum_{2,t}&=\sum_{i=1}^n(x_{t+1,i}^2-x_{t,i}^2)\\ &=\sum_{i=1}^n((x_{t,i}+v_i)^2-x_{t,i}^2)\\ &=\sum_{i=1}^n(2x_{t,i}\times v_i+v_i^2)\\ &=2\sum_{i=1}^nx_{t,i}v_i+sum_{v^2} \end{aligned}\]

\[\begin{aligned} sum_{2,t}-sum_{2,t-1}&=\sum_{i=1}^n(x_{t,i}^2-x_{t-1,i}^2)\\ &=\sum_{i=1}^n(x_{t,i}-(x_{t,i}-v_i)^2)\\ &=\sum_{i=1}^n(2x_{t,i}\times v_i-v_i^2)\\ &=2\sum_{i=1}^nx_{t,i}v_i-sum_{v^2} \end{aligned}\]

所以有 \((sum_{2,t+1}-sum_{2,t})-(sum_{2,t}-sum_{2,t-1})=2sum_{v^2}\)

\(t_0<3\) 时,可以得出 \(\displaystyle sum_{v^2}=\frac{sum_{2,3}-2sum_{2,4}+sum_{2,5}}{2}\);否则可以得出 \(\displaystyle sum_{v^2}=\frac{sum_{2,0}-2sum_{2,1}+sum_{2,2}}{2}\)

一种比较暴力的做法是枚举 \(t_0\) 时刻的所有的坐标,判断修正后是否满足条件。当然还有 \(O(1)\) 的做法。

我们可以假设被修改的坐标为 \(x\),并且我们知道修正的差值 \(\Delta x\)
根据小学数学知识,我们可以列出一个一元一次方程,然后就可以 \(O(1)\) 求出 \(x\)

限于篇幅,这里不再赘述,读者可以自己在草稿纸上推一下。

程序

AC 记录

#include<cstdlib>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<queue>
#include<cstdio>
#include<iostream>
#include<vector>
#include<map>
#include<cmath>
#include<iomanip>
#include<string>
#include<stack>
#define ll long long
#define ull unsigned long long
#define ls rt<<1
#define rs rt<<1|1
using namespace std;
const int MAXN=1000;
const int N=MAXN+10;
//#define more_test
//#define need_init
#ifdef more_test
int T;
#endif

int n,T,x[N][N];

int sum1[N],sum2[N],t0,cnt,dx,sumv,sumv2;bool flag;

void SOLVE(int test_id){
	scanf("%d%d",&n,&T);
	for(int i=0;i<T;++i)for(int j=1;j<=n;++j)scanf("%d",&x[i][j]);
	for(int i=0;i<T;++i)for(int j=1;j<=n;++j)sum1[i]+=x[i][j],sum2[i]+=x[i][j]*x[i][j];
	sumv=sum1[1]-sum1[0];
	for(int i=2;i<T;++i){
		if(sum1[i]-sum1[i-1]!=sum1[1]-sum1[0]){
			if(!flag)t0=i,flag=true,dx=sumv-(sum1[i]-sum1[i-1]);
			++cnt;
		}
	}
	if(cnt>2)t0=1,sumv=sum1[3]-sum1[2],dx=sumv-(sum1[1]-sum1[0]);
	if(t0<3)sumv2=(sum2[3]+sum2[5]-2*sum2[4])/2;
	else sumv2=(sum2[2]+sum2[0]-2*sum2[1])/2;
	printf("%d ",t0);
	if(t0<T-1)printf("%d",(sum2[t0+1]+sum2[t0-1]-2*sum2[t0]-2*sumv2-2*dx*dx)/(4*dx)+dx);
	else printf("%d",(2*sum2[T-2]-sum2[T-3]-sum2[T-1]+2*sumv2-dx*dx)/(2*dx)+dx);
	fflush(stdout);
}

int main(){
	#ifdef need_init
	init();
	#endif
	#ifdef more_test
	scanf("%d",&T);
	for(int i=1;i<=T;++i)SOLVE(i);
	#else
	SOLVE(1);
	#endif
	return 0;
}
posted @ 2025-03-18 19:03  LXcjh4998  阅读(7)  评论(0)    收藏  举报