BZOJ3613: [Heoi2014]南园满地堆轻絮

分析:

构造数据时间有些长,可以用秦九韶优化一下。

二分答案+贪心,即:另每一个b[i]尽可能的小的同时满足题意,在枚举过程中,判断是否存在一个b[i-1]>a[i]+x

如果存在,那么向右找

如果不存在,向左找

附上代码:

#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <queue>
//#include <ctime>
using namespace std;
#define N 5000005
#define ll long long
int a[N],f[N],b[N],n,Sa,Sb,Sc,Sd,mod;
int F(int x)
{
	if(f[x]) return f[x];
	return f[x]=((1ll*Sa*a[x]%mod+Sb)*a[x]*a[x]%mod+(1ll*Sc*a[x]%mod+Sd)%mod)%mod;
}
int check(int x)
{
	b[0]=-1<<30;
	for(int i=1;i<=n;i++)
	{
		if(a[i]>b[i-1]+x)
		{
			b[i]=a[i]-x;
		}else
		{
			if(a[i]+x<b[i-1])return 0;
			b[i]=b[i-1];
		}
	}
	return 1;
}
int main()
{
	a[0]=0;
	scanf("%d%d%d%d%d%d%d",&n,&Sa,&Sb,&Sc,&Sd,&a[1],&mod);
	for(int i=2;i<=n;i++)a[i]=(F(i-1)+F(i-2))%mod;
	int l=0,r=1<<30;
	while(l<r)
	{
		int m=(l+r)>>1;
		if(check(m)) r=m;
		else l=m+1;
	}
	printf("%d\n",l);
	return 0;
}

  卡了一下常数(loj上需要卡一下常数,bzoj和洛谷不用,开O2跑的飞快)

posted @ 2018-05-07 21:49  Winniechen  阅读(152)  评论(0编辑  收藏  举报