• [bzoj1011] [HNOI2008]遥远的行星


    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
    

    Solution

    神仙操作。。

    注意到:只要结果的相对误差不超过5%即可,可以考虑近似计算。

    对于第(i)个位置,答案显然就是:

    [sum_{k=1}^{lfloor acdot i floor}frac{m_im_k}{i-k} ]

    如果(acdot i)较小,直接计算就好了。

    否则可以考虑分成若干段,近似计算,对于一个区间([a,b]),可以把答案近似为(m_icdot frac{sum_{k=a}^{b}m_k}{i-(a+b)/2}),其实就是把分母全看成一样的。

    显然,分的段数越高,效率越低,答案越精确,我这里是分了(100)段。

    #include<bits/stdc++.h>
    using namespace std;
    
    void read(int &x) {
    	x=0;int f=1;char ch=getchar();
    	for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f;
    	for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f;
    }
    
    #define write(x) printf("%d
    ",x)
    #define ll long long 
    #define lf double
    
    const int maxn = 2e5+10;
    const int T = 100;
    
    int m[maxn],n;
    ll sum[maxn];
    lf a;
    
    int main() {
    	read(n);scanf("%lf",&a);
    	for(int i=1;i<=n;i++) read(m[i]),sum[i]=sum[i-1]+1ll*m[i];
    	for(int i=1;i<=n;i++) {
    		int x=floor(a*(lf)i);
    		double ans=0;	
    		if(x<=1000) for(int k=1;k<=x;k++) ans+=(lf)m[i]*m[k]/(lf)(i-k);
    		else {
    			int t=x/T;
    			for(int k=1;k<=x;k+=t) {
    				int ed=min(x,k+t-1);
    				int mid=(k+ed)>>1;
    				ans+=(lf)m[i]*(sum[ed]-sum[k-1])/(lf)(i-mid);
    			}
    		}printf("%.6lf
    ",ans);
    	}
    	return 0;
    }
    
  • 相关阅读:
    Scala-函数
    Scala--循环
    scala(一)
    拦截器filter
    Ajax实现分页二
    并发1
    泛型
    协议protocol
    结构体structure
    类的继承
  • 原文地址:https://www.cnblogs.com/hbyer/p/10351771.html
Copyright © 2020-2023  润新知