模擬賽 數列(時間限制 1s;內存限制:128MB)

題目描述

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;
}
發佈了367 篇原創文章 · 獲贊 2 · 訪問量 26萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章