luogu P3198 [HNOI2008]遥远的行星

bzoj

洛谷

这题意是不是不太清楚

真正题意:求$$f_i=sum_{j=1}^{lfloor iA floor} frac{M_iM_j}{i-j}$$

似乎只能(O(n*lfloor n*A floor))

但是,注意只要结果的相对误差不超过 5% 即可

于是对于较大的(i)来说,(f_i)可以近似的看为(M_i*frac{sum_{j=1}^{lfloor i*A floor} M_j}{i-frac{lfloor i*A floor}{2}})

因为(A)是一个不超过0.35的实数,并且(i)较大时(i-j)也会比较大,所以近似一下可以接受

至于为什么,emmm你猜

#include<bits/stdc++.h>
#define LL long long
#define il inline
#define re register
#define inf 2099999999
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define db double
#define eps (1e-5)
 
using namespace std;
const int N=100000+10;
il LL rd()
{
    re LL x=0,w=1;re char ch=0;
    while(ch<'0'||ch>'9') {if(ch=='-') w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9') {x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
    return x*w;
}
int n,nn;
db a,m[N],ans;
 
int main()
{
  n=rd();scanf("%lf",&a);
  for(int i=1;i<=n;i++) scanf("%lf",&m[i]);
  nn=min(3000,n);
  for(int i=1;i<=nn;i++)
    {
      int mm=(int)(i*a+eps);
      ans=0;
      for(int j=1;j<=mm;j++) ans+=m[j]/(db)(i-j);
      ans*=m[i];
      printf("%.8lf
",ans);
    }
  db tm=0;
  for(int i=nn+1,la=1;i<=n;i++)
    {
      int mm=(int)(i*a+eps);
      while(la<=mm) tm+=m[la++];
      ans=m[i]*tm/((db)i-(db)mm/2);
      printf("%.8lf
",ans);
    }
  return 0;
}
原文地址:https://www.cnblogs.com/smyjr/p/9671664.html