題目描述
Czy手上有一個長度爲n的數列,第i個數爲xi。他現在想知道,對於給定的a,b,c,他要找到一個i,使得a*(i+1)*xi2+(b+1)*i*xi+(c+i)=0成立。
如果有多個i滿足,Czy想要最小的那個i。
Czy有很多很多組詢問需要你回答,多到他自己也不確定有多少組。所以在輸入數據中a=b=c=0標誌着Czy的提問的結束。
更加糟糕的是,Czy爲了加大難度,決定對數據進行加密以防止離線算法的出現。
假設你在輸入文件中讀到的三個數爲a0,b0,c0,那麼Czy真正要詢問的a=a0+LastAns,b=b0+LastAns,c=c0+LastAns.
LastAns的值是你對Czy的前一個詢問的回答。如果這是第一個詢問,那麼LastAns=0。
所有的詢問都將會按上述方式進行加密,包括標誌着詢問的結束的那個詢問也是這樣。
輸入
輸入文件爲 seq.in輸入文件第一行包含一個整數n,表示數列的長度。
輸入文件第二行包含n個整數,第i個數表示xi的值。
接下來若干行,每行三個數,表示加密後的a,b,c值(也就是上文所述的a0,b0,c0)
輸出
輸出文件爲 seq.out包含若干行,第i行的值是輸入文件中第i個詢問的答案。注意,你不需要對標誌着詢問結束的那個詢問作答。
同時,標誌着詢問結束的詢問一定是輸入文件的最後一行。也就是,輸入文件不會有多餘的內容。
樣例輸入
seq.in seq.out
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
數據範圍
對於40%的數據,滿足N<=1000,需要作出回答的詢問個數不超過1000.對於100%的數據,滿足N<=50000,需要作出回答的詢問個數不超過500000,xi的絕對值不超過30000,解密後的a的絕對值不超過50000,解密後的b的絕對值不超過10^8,解密後的c的絕對值不超過10^18.
題解
我語文不好……人家說不用我就真沒用。
話說根據a=a0+LastAns,b=b0+LastAns,c=c0+LastAns。可知最後一個詢問的答案。然後把那個式子展開,就可以得出計算lastans的式子。
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<cmath>
#include<algorithm>
#define ll long long
using namespace std;
int n,x[50002],zz;
struct cans{ll a,b,c;} s[500002];
ll ans[500002];
void init()
{
scanf("%d",&n);
int i;
for(i=1;i<=n;i++) scanf("%d",&x[i]);
while(true)
{zz++;
scanf("%I64d%I64d%I64d",&s[zz].a,&s[zz].b,&s[zz].c);
if(s[zz].a==s[zz].b&&s[zz].a==s[zz].c) return;
}
}
ll calcu(int i)
{
ll A,B;
A=-s[i].a*(ans[i]+1)*x[ans[i]]*x[ans[i]]-(s[i].b+1)*ans[i]*x[ans[i]]-s[i].c-ans[i];
B=(ans[i]+1)*x[ans[i]]*x[ans[i]]+ans[i]*x[ans[i]]+1;
return A/B;
}
void work()
{
int i;
ans[zz-1]=0-s[zz].a;
for(i=zz-1;i>1;i--)
ans[i-1]=calcu(i);
for(i=1;i<zz;i++) printf("%I64d\n",ans[i]);
}
int main()
{
freopen("seq.in","r",stdin);
freopen("seq.out","w",stdout);
init(); work();
return 0;
}