数列(倒推)
CYX 手上有一个长度为n 的数列,第i 个数为xi。
她现在想知道,对于给定的a,b,c,她要找到一个i,使得a*(i + 1) * xi2 + (b + 1) * i * xi + (c + i) = 0成立。
如果有多个i 满足,CYX 想要最小的那个i。
CYX 有很多很多组询问需要你回答,多到她自己也丌确定有多少组。所以在输入数据中a=b=c=0 标志着CYX的提问结束。
更加糟糕的是,CYX 为了加大难度,决定对数据进行加密以防止离线算法的出现。
假设你在输入文件中读到的三个数为a0,b0,c0,那么CYX 真正要询问的a = a0 + LastAns,b = b0 + LastAns,c = c0 + LastAns。
LastAns的值是你对CYX 的前一个询问的回答。如果这是第一个询问,那么LastAns=0。
所有的询问都将会按上述方式进行加密,包括标志着询问的结束的那个询问也是这样。
【输入】
输入文件为 seq.in
输入文件第一行包含一个整数n,表示数列的长度。
输入文件第二行包含n 个整数,第i 个数表示xi 的值。
接下来若干行,每行三个数,表示加密后的a,b,c 值(也就是上文所述的a0,b0,c0)
【输出】
输出文件为 seq.out
包含若干行,第i 行的值是输入文件中第i 个询问的答案。注意,你不需要对标志着询问结束的那个询问作答。
同时,标志着询问结束的询问一定是输入文件的最后一行。也就是,输入文件不会有多余的内容。
【输入输出样例】
seq.in
5 -2 3 1 -5 2
-5 -4 145-1 -6 -509
-9 -14 40
-3 -13 21
-3 -3 -3
seq.out
5
4
3
3
【数据范围】
对于40%的数据,满足N<=1000,需要作出回答的询问个数不超过1000。
对于100%的数据,满足N<=50000,需要作出回答的询问个数不超过500000,xi 的绝对值不超过30000,
解密后的a 的绝对值不超过50000,解密后的b 的绝对值不超过10^8,解密后的c 的绝对值不超过10^18。
N <= 50000,询问个数m不超过500000,所以O(nm)过不了,但是我们观察到最后的a,b,c解密后为0,那么我们可以以此倒推出前一个的答案,以此类推,时间复杂度可以简化到O(n)。
int n; int top = 0; scanf("%d",&n); for(int i=1;i<=n;i++)scanf("%d",&x[i]); while(scanf("%d%d%lld",&a[top],&b[top],&c[top]) == 3) top++; top--; long long int lastans = 0 - a[top];//解密后为 0 top--; anss[top] = lastans; long long int ans = 0; for(int i=top;i>0;i--){//倒推 ans = (long long int)a[i] * (lastans + 1)*x[lastans] * x[lastans] + (b[i] + 1) * lastans * x[lastans] + c[i] + lastans; lastans = (long long int)-ans / ((lastans + 1)*x[lastans] * x[lastans] + lastans * x[lastans] + 1); anss[i - 1] = lastans; } for(int i=0;i<=top;i++) printf("%lld\n",anss[i]);