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跑的飞快)