(纪中)2034. 神奇的项链(fett)【二分+数学】

(File IO): input:fett.in output:fett.out
时间限制: 1000 ms 空间限制: 128000 KB 具体限制
Goto ProblemSet


题目描述
从前有一条神奇的项链,为什么说它神奇呢?因为它有两个性质:

  1. 神奇的项链可以拉成一条线,线上依次是 N N N个珠子,每个珠子有一个能量值 E i Ei Ei
  2. 除了第一个和最后一个珠子,其他珠子都满足 E i = ( E i − 1 + E i + 1 ) / 2 + D i Ei=(Ei-1+Ei+1)/2+Di Ei=(Ei1+Ei+1)/2+Di
    由于这条项链很长,我们只能知道其两端珠子的能量值。并且我们知道每个珠子的 D i Di Di是多少。请聪明的你求出这 N N N个珠子的能量值分别是多少。

输入
第一行三个整数 N 、 E 1 、 E N , N、E1、EN, NE1EN表示珠子个数 N N N,第一个珠子和第 N N N 个珠子的能量值。
第二行 N − 2 N-2 N2 个整数,表示第 2 2 2 个珠子到第 N − 1 N-1 N1个珠子的 D i Di Di

输出
输出仅一行, N N N 个整数,表示 1 1 1 N N N 个这 N N N 个珠子各自的能量值 E i Ei Ei
请放心,数据保证对于任意珠子满足 ( E i − 1 + E i + 1 ) M o d 2 = 0 (Ei-1+Ei+1)Mod 2=0 (Ei1+Ei+1)Mod2=0


样例输入
Sample Input 1:
4 1 4
0 0

Sample Input 2:
10 1 22
1 2 -3 5 1 4 2 -1

样例输出
Sample Output 1:
1 2 3 4

Sample Output 2:
1 14 25 32 45 48 49 42 31 22


数据范围限制
40 40 40%的数据 1 < N < = 100 11<N<=100
70 70 70%的数据 1 < N < = 5 , 000 11<N<=5,000,所有数据(包括计算中的)不超过 1 0 9 10^9 109
100 100 100%的数据 1 < N < = 500 , 000 11<N<=500,000 ∣ E 1 ∣ 、 ∣ E N ∣ < = 1 0 1 4 , ∣ D i ∣ < = 1 0 4 |E1|、|EN|<=10^14,|Di|<=10^4 E1EN<=1014Di<=104


解题思路
二分答案
通过 E i = ( E i − 1 + E i + 1 ) / 2 + D i Ei=(Ei-1+Ei+1)/2+Di Ei=(Ei1+Ei+1)/2+Di,我们可以推出 E i + 1 = ( E i − D i ) ∗ 2 − E i − 1 Ei+1=(Ei-Di)*2-Ei-1 Ei+1=(EiDi)2Ei1
也就是说知道E2就知道全部
二分 E 2 E2 E2
如果 E n En En和输入进来的一样,就输出


代码

#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#include<algorithm>
#include<iomanip>
#include<cmath>
using namespace std;
long long n,b,d[500010],a[500010];
long long l=-2147483647,r=-l,k,mid;
int main(){
	freopen("fett.in","r",stdin);
    freopen("fett.out","w",stdout);
    scanf("%lld%lld%lld",&n,&a[1],&k);
    for(int i=2;i<n;i++)
    	scanf("%lld",&d[i]);
    while(l<=r){
    	mid=(l+r)/2;
    	a[2]=mid;
    	for(long long i=2;i<n;i++){
			a[i+1]=(a[i]-d[i])*2-a[i-1];
		}
		if(a[n]==k)
		{
			for(long long i=1;i<=n;i++)
				printf("%lld ",a[i]);
			return 0;
		}
		if(a[n]>k)
			r=mid;
		else
			l=mid;
	}
	return 0;
}

你可能感兴趣的:(纪中,二分,数学)