1. 程式人生 > >1011: [HNOI2008]遙遠的行星

1011: [HNOI2008]遙遠的行星

queue getch getchar() HA inline efi LG online put

1011: [HNOI2008]遙遠的行星

Time Limit: 10 Sec Memory Limit: 162 MBSec Special Judge
Submit: 5382 Solved: 2007
[Submit][Status][Discuss]

Description

  直線上N顆行星,X=i處有行星i,行星J受到行星I的作用力,當且僅當i<=AJ.此時J受到作用力的大小為 Fi->j=
Mi*Mj/(j-i) 其中A為很小的常量,故直觀上說每顆行星都只受到距離遙遠的行星的作用。請計算每顆行星的受力
,只要結果的相對誤差不超過5%即可.

Input

  第一行兩個整數N和A. 1<=N<=10^5.0.01< a < =0.35,接下來N行輸入N個行星的質量Mi,保證0<=Mi<=10^7

Output

  N行,依次輸出各行星的受力情況

Sample Input

5 0.3
3
5
6
2
4

Sample Output

0.000000
0.000000
0.000000
1.968750
2.976000

HINT

  精確結果應該為0 0 0 2 3,但樣例輸出的結果誤差不超過5%,也算對

這個題的方法真的玄學。。。很明顯我們發現需要枚舉每個行星,然後計算和加起來,但是這樣是n^2的復雜度很明顯不對,那麽我們還有什麽比較高科技的操作麽?線段樹?明顯不行。。平衡樹?貌似不是這類問題的方法吧。。。然後可以發現這題有special judge,嗯,根據我的判斷,估計應該有那種很2的代碼A掉。。看了看BZOJ的評測記錄,技術分享圖片

好了,我估計AC代碼就是:

puts("-nan");
    return 0;

交上去一看,果然A了。。。。

好了好了不扯這些,實際上這道題因為有了只要結果的相對誤差不超過5%即可.這句話,而且發現a的取值很小,所以我們大可以大膽的使用一些奇怪的方法,比如分塊。。。我們暴力計算一個自己確定的T值以內大小的數據,然後對於其它的大於T的,我們分成大小為T的幾塊,求出中間值得分母,然後代入式子就可以了,因為a很小,所在T取100時也不會超過5%的誤差。

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <iostream>
#include 
<cstdlib> #include <cmath> #include <string> #include <cstring> #include <cstdio> #include <algorithm> #include <queue> #include <set> #include <map> #define re register #define max(a,b) ((a)>(b)?(a):(b)) #define min(a,b) ((a)<(b)?(a):(b)) #define mid ((i-j+i-j+len-1)*0.5) using namespace std; typedef long long ll; typedef unsigned long long ull; #define ms(arr) memset(arr, 0, sizeof(arr)) const int inf = 0x3f3f3f3f; ll a[100005],sum[100005],n; double ans[100005],A; inline int read() { int x=0,c=1; char ch= ; while((ch>9||ch<0)&&ch!=-)ch=getchar(); while(ch==-) c*=-1,ch=getchar(); while(ch<=9&&ch>=0)x=x*10+ch-0,ch=getchar(); return x*c; } int main() { //freopen("date.in","r",stdin); n=read();scanf("%lf",&A); for(re int i=1;i<=n;i++){ a[i]=read(); sum[i]=sum[i-1]+a[i]; } for(re int i=1;i<=n;i++){ int lenth=int(A*i); if(lenth<=80){ for(re int j=1;j<=lenth;j++) ans[i]+=(a[i]*a[j])*1.0/(i-j); }else{ int len=lenth/80; for(re int j=len;j<=len*80;j+=len) ans[i]+=(sum[j]-sum[j-len])*a[i]*1.0/mid; for(re int j=len*80+1;j<=lenth;j++) ans[i]+=(a[i]*a[j])*1.0/(i-j); } } for(re int i=1;i<=n;i++) printf("%.10lf\n", ans[i]); return 0; }

很奇怪的是這代碼洛谷A了但是bzoj並沒有A掉。

1011: [HNOI2008]遙遠的行星