【2020去世模拟赛2】一道防AK好题

题目描述

Lemon认为在第一届『Citric』杯模拟赛中出的题目太简单了,于是他决定,这次要给参赛选手们一个下马威! ^_^

Lemon手上有一个长度为n的数列,第i个数为xi。
他现在想知道,对于给定的a,b,c,他要找到一个i,使得a(i+1)xi^2+(b+1)ixi+(c+i)=0成立。
如果有多个i满足,Lemon想要最小的那个i。
Lemon有很多很多组询问需要你回答,多到他自己也不确定有多少组。所以在输入数据中a=b=c=0标志着Lemon的提问的结束。

更加糟糕的是,Lemon为了加大难度,决定对数据进行加密以防止离线算法的出现。
假设你在输入文件中读到的三个数为a0,b0,c0,那么Lemon真正要询问的a=a0+lastans,b=b0+lastans,c=c0+lastans.
lastans的值是你对Lemon的前一个询问的回答。如果这是第一个询问,那么lastans=0
所有的询问都将会按上述方式进行加密,包括标志着询问的结束的那个询问也是这样。

为提高读入效率,请用scanf(),而不能用cin,即使加sync_with_stdio(false)也不行!

对于不确定数量的数据,当读入完最后一行数据后,再次调用scanf(),会返回-1,以此可判断读入是否结束。

输入格式

输入文件第一行包含一个正整数n,表示数列的长度。
输入文件第二行包含n个整数,第i个数表示xi的值。
接下来若干行,每行三个数,表示加密后的a,b,c值(也就是上文所述的a0,b0,c0)

输出格式

包含若干行,第i行的值是输入文件中第i个询问的答案。注意,你不需要对标志着询问结束的那个询问作答。
同时,标志着询问结束的询问一定是输入文件的最后一行。也就是,输入文件不会有多余的内容。

样例输入

5
-2 3 1 -5 2 
-5 -4 145
-1 -6 -509
-9 -14 40
-3 -13 21
-3 -3 -3

样例输出

5
4
3
3

数据范围与提示

第一个询问中,真实的a=-5+0=-5,b=-4+0=-4,c=145+0=145(第一个询问中lastans=0)
带入发现,i=5时,-5(5+1)2^2+(-4+1)52+145+5=0,而其他的i均不符合条件。所以答案是5.
第二个询问中,真实的a=-1+5=4,b=-6+5=-1,c=-509+5=-504(lastans是上一个询问的答案的值,也就是5)
经带入发现,i=4时,4(4+1)(-5)^2+(-1+1)4(-5)+(-504)+4=0,满足条件,而其他的i均不满足条件,所以答案是4.
同理,第三个询问中真实的a=-5,b=-10,c=44.答案i=3
第四个询问中真实的a=0,b=-10,c=24,答案i=3
第五个询问中真实的a=0,b=0,c=0,此时我们发现这是一个标志着结束的询问,这个询问我们无需作出回答。

对于40%的数据,满足N<=1000,需要作出回答的询问个数不超过1000.
对于100%的数据,满足N<=50000,需要作出回答的询问个数不超过500000,xi的绝对值不超过30000,解密后的a的绝对值不超过50000,解密后的b的绝对值不超过10^8,解密后的c的绝对值不超过10^18.

Solution

我真的佛了。

这道题简直是玄之又玄。你会发现,最后一个提问的答案就是最后结尾的\(-a或-b或-c\)

我们将答案代回式子,可以解出再上个提问的答案。。。

没错,这道题就是这么做的。。。

P.S.:如果你无限\(RE\)的话请不要魔改,可以康康式子有没有推错。(血的教训QWQ

#include <cstdio>
typedef long long ll;

int n, cnt;
ll x[50005], A, B, C, id, ans[500005];
struct node {
    ll a, b, c;
    node() {}
    node(const ll x, const ll y, const ll z) {a = x, b = y, c = z;}
}q[500005];

int main() {
    scanf("%d", &n);
    for(int i = 1; i <= n; ++ i) scanf("%lld", &x[i]);
    while(scanf("%lld %lld %lld", &A, &B, &C) != -1)
        q[++ cnt] = node(A, B, C);
    id = -q[cnt].a;
    ans[cnt] = id;
    for(int i = cnt - 1; i >= 1; -- i) {
        ll chu = (0ll + x[id] * x[id] * (id + 1) + x[id] * id + 1);
        if(chu == 0) ans[i] = 1;
        else ans[i] = -(0ll + q[i].a * (id + 1) * x[id] * x[id] + x[id] * id * (q[i].b + 1) + q[i].c + id) / chu;
        id = ans[i];
    }
    for(int i = 2; i <= cnt; ++ i) printf("%lld\n", ans[i]);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/AWhiteWall/p/12403095.html