• 一道题19


    $n leq 100000$的数列给$m leq 100000$个操作:操作一,单点修改;操作二,现给$t$种颜色,每种颜色数量给出,加起来为$n-1$,对除了询问给的$k$以外的每个数随机涂色;对一个$k$开始,公差$d$,往左右延伸的下标等差数列$a_i=k+id,L<=i<=R,L<=0<=R$,取极小的$L$和极小的$R$使得这些数字的颜色与$k$相同,加进答案,选择一种给$k$染色的方案($t$种之一)使期望答案最小,并输出这个答案。

    什么鬼畜操作。。

    首先$c$肯定选最小的一个,把期望分解成每一个数字选中的概率,对$K$右边的数,就是他左边一坨数(下标每次$-d$,直到$K+d$)和他自己都选中的的概率,就是他对答案有贡献的概率。$c$较小时这个概率乘没几下就变0了,但$c$可能达到$n-1$级别。

    仔细分析,$c$只有在$t=1$时才会使概率很大,此时概率为1,就相当于一个等差数列下标的数字求和,可以分块。而$t>1$后,$c$最大为$frac{n-1}{2}$,此时一个,两个,三个颜色与$K$相同的概率分别是$frac{c}{n-1},frac{c}{n-1}*frac{c-1}{n-2},frac{c}{n-1}*frac{c-1}{n-2}*frac{c-2}{n-3}...$,第一个数字只有$frac{1}{2}$,后面乘不多次就会变得很小,于是算到一定程度,概率很小可以忽略时退出循环。

     1 //#include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 //#include<time.h>
     5 //#include<complex>
     6 //#include<set>
     7 //#include<queue>
     8 //#include<vector>
     9 #include<algorithm>
    10 #include<stdlib.h>
    11 using namespace std;
    12 
    13 #define LL long long
    14 int qread()
    15 {
    16     char c; int s=0,f=1; while ((c=getchar())<'0' || c>'9') (c=='-') && (f=-1);
    17     do s=s*10+c-'0'; while ((c=getchar())>='0' && c<='9'); return s*f;
    18 }
    19 
    20 //Pay attention to '-' , LL and double of qread!!!!
    21 
    22 int n,m,bl;
    23 #define maxn 100011
    24 int a[maxn],b[411][411];
    25 
    26 int main()
    27 {
    28     n=qread(); bl=min(n,400); m=qread();
    29     for (int i=1;i<=n;i++) a[i]=qread();
    30     for (int i=1;i<=bl;i++)
    31         for (int j=1;j<=i;j++)
    32             for (int k=j;k<=n;k+=i)
    33                 b[i][j]+=a[k];
    34     
    35     int op,t,K,d,c;
    36     while (m--)
    37     {
    38         op=qread();
    39         if (op==1)
    40         {
    41             K=qread(); d=qread();
    42             for (int i=1;i<=bl;i++)
    43             {
    44                 int j=(K-1)%i+1;
    45                 b[i][j]+=d-a[K];
    46             }
    47             a[K]=d;
    48         }
    49         else
    50         {
    51             t=qread(); K=qread(); d=qread(); c=qread(); t--;
    52             if (t==0) printf("%d.000000
    ",b[d][(K-1)%d+1]);
    53             else
    54             {
    55                 while (t--) {c=min(c,qread());}
    56                 double ans=a[K],tmp=1;
    57                 for (int i=K+d,w=0;i<=n && w<=bl;i+=d,w++)
    58                 {
    59                     if (w==c) tmp=0;
    60                     if (tmp<1e-12) break;
    61                     tmp*=1.0*(c-w)/(n-1-w);
    62                     ans+=tmp*a[i];
    63                 }
    64                 tmp=1;
    65                 for (int i=K-d,w=0;i>=1 && w<=bl;i-=d,w++)
    66                 {
    67                     if (w==c) tmp=0;
    68                     if (tmp<1e-12) break;
    69                     tmp*=1.0*(c-w)/(n-1-w);
    70                     ans+=tmp*a[i];
    71                 }
    72                 printf("%.6lf
    ",ans);
    73             }
    74         }
    75     }
    76     return 0;
    77 }
    View Code
  • 相关阅读:
    C# 使用正则表达式按指定长度分割字符串
    C# vs2017创建Com组件,并注册
    js将4个字节型字符串转为Float
    js 替换字符串中的双引号
    js截取两个字符串之间的子字符串
    C# Winform设计运行时,界面模糊
    Scala字节数组转换为数字
    Scala环境搭建及Intellij IDEA安装
    C# 循环时,操作另外一个进程直到操作完成,循环继续执行
    如何搭建node
  • 原文地址:https://www.cnblogs.com/Blue233333/p/9179620.html
Copyright © 2020-2023  润新知