zoukankan      html  css  js  c++  java
  • 【纪中集训2019.3.26】获取名额

    描述

    描述:

    (n)场省选选拔赛,每场的前(a_i)名可以获得省选资格;

    假设(Moorhsum)只参加第([l,r])场比赛,且每一场排名在([1,x])随机;

    求他获得省选资格的概率;

    范围:

    $1 le n , q le 600000 , 1 le x le 10^9 , 1 le l le r le n $;

    数据保证对于任意(i)(a_i lt x);

    当你的答案和标准答案的误差不超过(10^{-6})是被认为是正确的;

    (512MB);

    题解

    • 只需要统计$ Pi_{i=l}^{r} (1-frac{a_i}{x})$;

    • $= exp(sum_{i=l}^{r} ln(1-frac{a_i}{x})) $;

    • (frac{a_i}{x} lt 1)所以里面可以直接泰勒展开:

    • $ = - sum_{i=l}^{r} sum_{j=1}^{infty} frac{a_i^j}{j x^j} = -sum_{i=j}^{infty}frac{1}{ix^i} sum_{j=l}^{r} a_j^i $;

    • 貌似只要(infty)(50)左右,预处理$sum_{i=l}^{r} a_j^i $就可以了;

    • 实测一下会发现范围和精度有很大问题;

    • 范围问题直接考虑将(x=/max(a_i),a_i/=max(a_i))就不会爆(double)了;

    • (a_i/x)较大时,(ln)里面的东西会比较接近(0),很难保证精度;

    • (a_i/x)设置一个(lim),当(a_i/x>lim)时直接算,再递归左右区间;

    • (lim)(0.5)是可以过的;

      #include<bits/stdc++.h>
      #define ld double
      #define il inline
      using namespace std;
      const int N=600010;
      int n,m,lg[N],f[N][21],bin[21];
      ld sum[N][51],a[N],X,tmp;
      il char gc(){
      	static char*p1,*p2,s[1000000];
      	if(p1==p2)p2=(p1=s)+fread(s,1,1000000,stdin);
      	return(p1==p2)?EOF:*p1++;
      }
      il int rd(){
      	int x=0;char c=gc();
      	while(c<'0'||c>'9')c=gc();
      	while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+c-'0',c=gc();
      	return x;
      }
      il int Max(int x,int y){return a[x]>a[y]?x:y;}
      il int ask(int x,int y){
      	int t=lg[y-x+1];
      	return Max(f[x][t],f[y-bin[t]+1][t]);
      }
      il ld cal(int l,int r){
      	ld re=0,t=1;
      	for(int i=1;i<=50;++i){
      		t*=X;re-=(sum[r][i]-sum[l-1][i])/(t*i);
      	}
      	return exp(re);
      }
      void solve(int l,int r){
      	int mid=ask(l,r);
      	if(a[mid]/X<0.5){tmp*=cal(l,r);return;}
      	tmp*=1-a[mid]/X;
      	if(l<mid)solve(l,mid-1);
      	if(mid<r)solve(mid+1,r);
      } 
      int main(){
      	freopen("orz.in","r",stdin);
      	freopen("orz.out","w",stdout);
      	n=rd();m=rd();ld mx=0;
      	for(int i=1;i<=n;++i)a[i]=rd(),mx=max(a[i],mx);
      	for(int i=1;i<=n;++i)a[i]/=mx;
      	for(int i=bin[0]=1;i<=20;++i)bin[i]=bin[i-1]<<1;
      	lg[0]=-1;for(int i=1;i<=n;++i)f[i][0]=i,lg[i]=lg[i>>1]+1;
      	for(int i=1;i<=20;++i)
      	for(int j=1;j+bin[i]-1<=n;++j){
      		f[j][i]=Max(f[j][i-1],f[j+bin[i-1]][i-1]);
      	}
      	for(int i=1;i<=n;++i){
      		ld t=1;
      		for(int j=1;j<=50;++j){
      			t*=a[i];
      			sum[i][j]=sum[i-1][j]+t;
      		}
      	}
      	for(int i=1,l,r;i<=m;++i){
      		l=rd();r=rd();X=rd()/mx;
      		tmp=1;solve(l,r);
      		ld ans=1-tmp;
      		printf("%.10lf
      ",ans); 
      	}
      	return 0;
      }
      
  • 相关阅读:
    Exp9 Web安全基础
    EXP8 Web基础
    Exp7 网络欺诈防范
    Exp6 信息搜集与漏洞扫描
    Exp5 MSF基础应用
    Exp4 恶意代码分析
    Exp3 免杀原理与实践
    Exp2 后门原理与实践 20154317
    正则表达Regex替换标签
    正则表达式
  • 原文地址:https://www.cnblogs.com/Paul-Guderian/p/10602643.html
Copyright © 2011-2022 走看看