Problem Description
You are given an array that consists of n integer numbers. You have to change at most K elements of this array, so that the resulting array will be a arithmetic progression. From all the possible arithmetic progressions, you should choose most beautiful.
You can uniquely define the arithmetic progression by two numbers a0 and d - the first element of the given progression and the step that defines next element. (ai = a0+i * d). The progression A(a0 , d0) is more beautiful than the progression B(b0, d1) iff (a0 < b0 or (a0 = b0 and d0 < d1))
Input
The first line contains two integers N and K denoting the number of elements in the given array and the number of elements that you can changeThe second line contains N space-separated integers A1, A2, ..., AN denoting the given array.
题目大意:
给你一个长度为n的序列,要你改动至多K个数,使之变为等差数列,我们用一个式子描述改变后的数列:ai=a0+i*d。要求改动后使a0尽量小,a0相同时d尽量小。
输出改动后的数列。
Output
Output a single line containing the resulting array with at most K changes. Mind that among all the arithmetic sequences you have to choose the most beautiful.In the given test data, it is always possible to recover at least one arithmetic progression under the constraints of the problem.
Constraints
2 ≤ N ≤ 1000000 ≤ K ≤ min(10, N-2)
-109 ≤ Ai ≤ 109
Example
Input:4 2
1 2 1 4
Output:
-5 -2 1 4
题解
这道题怪怪的,感觉codechef上的不少题想法都怪怪的。感谢lwher的思路。
K最多只有10个,意味着原数列已经很接进答案了——在n较大的情况下,我们随机抓两个数,很可能得到最终的a0和d(因为这两个数很有可能是不需要改动的),而在n较小的情况下,也一定保证至少有两个数不需要改动。
所以我们只要枚举前23位(其实13就够了,因为最多只改十个),选出两个数算出a0和d,带回原数组检验是否有<=K个数不满足ai的表达式即可。
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<cmath>
#include<algorithm>
#define ll long long
using namespace std;
int n,m,a[100002];
ll ansa=1<<30,ansd=1<<30;
void init()
{
scanf("%d%d",&n,&m);
int i;
for(i=1;i<=n;i++) scanf("%d",&a[i]);
}
void work1()
{
int i,j,k,w,ct;
ll t,d,a0;
for(i=1;i<n;i++)
for(j=i+1;j<=n;j++)
{t=a[j]-a[i]; w=j-i;
if(t%w!=0) continue;
d=t/w; a0=a[i]-i*d;
ct=0;
for(k=1;k<=n;k++)
{if(a[k]!=a0+k*d) ct++;
if(ct>m) break;
}
if(ct<=m)
{if(ansa>a0)
{ansa=a0; ansd=d;}
else if(ansa==a0&&ansd>d) ansd=d;
}
}
for(i=1;i<n;i++)
printf("%lld ",ansa+i*ansd);
printf("%lld\n",ansa+n*ansd);
}
void work2()
{
int i,j,k,w,ct;
ll t,d,a0;
for(i=1;i<23;i++)
for(j=i+1;j<=23;j++)
{t=a[j]-a[i]; w=j-i;
if(t%w!=0) continue;
d=t/w; a0=a[i]-i*d;
ct=0;
for(k=1;k<=n;k++)
{if(a[k]!=a0+k*d) ct++;
if(ct>m) break;
}
if(ct<=m)
{if(ansa>a0)
{ansa=a0; ansd=d;}
else if(ansa==a0&&ansd>d) ansd=d;
}
}
for(i=1;i<n;i++)
printf("%lld ",ansa+i*ansd);
printf("%lld\n",ansa+n*ansd);
}
int main()
{
init();
if(n<=22) work1();
else work2();
return 0;
}