zoukankan      html  css  js  c++  java
  • Random Query CodeForces

    题目

    翻译:

    给出一个n个数字的数列a[1],...,a[n],f(l,r)表示使a[l],a[l+1],...,a[r]组成的新序列中的重复元素只保留一个后,剩下元素的数量(如果l>r,则在计算前先交换l和r)。从1-n中分别选出两个数字l和r(两个数字选时各自独立,每个数字选出1-n的概率相等),求f(l,r)的数学期望。

    就是$dfrac {sum _{lleq n}^{l=1}sum _{rleq n}^{r=1}fleft( l,r ight) } {n^{2}}$

    插入数学公式

    然后,我参照这道题的做法写了一个O(log(n)*n^2)

     1 #include<cstdio>
     2 typedef long long LL;
     3 LL c[1001000];
     4 LL n,ans;
     5 LL a[1001000];
     6 LL next1[1001000];
     7 LL boo[1001000];
     8 LL lowbit(LL x)
     9 {
    10     return x&-x;
    11 }
    12 void add(LL num,LL x)
    13 {
    14     while(num<=n)
    15     {
    16         c[num]+=x;
    17         num+=lowbit(num);
    18     }
    19 }
    20 LL sum1(LL x)
    21 {
    22     LL ans=0;
    23     while(x>0)
    24     {
    25         ans+=c[x];
    26         x-=lowbit(x);
    27     }
    28     return ans;
    29 }
    30 LL sum(LL l,LL r)
    31 {
    32     return sum1(r)-sum1(l-1);
    33 }
    34 int main()
    35 {
    36     LL i,j;
    37     scanf("%lld",&n);
    38     for(i=1;i<=n;i++)
    39         scanf("%lld",&a[i]);
    40     for(i=n;i>=1;i--)
    41         next1[i]=boo[a[i]],boo[a[i]]=i;
    42     //boo[i]记录数字i第一次出现位置,next1[i]记录第i个数字下一次出现位置
    43     for(i=1;i<=n;i++)
    44         if(boo[a[i]]==i)
    45             add(i,1);
    46     for(i=1;i<=n;i++)
    47     {
    48         for(j=i+1;j<=n;j++)
    49             ans+=sum(i,j);
    50         if(next1[i]!=0)
    51             add(next1[i],1);
    52     }
    53     ans*=2;
    54     ans+=n;
    55     printf("%lf",(double)ans/(double)n/(double)n);
    56     return 0;
    57 }

    然后,就tle了。。。

    经过大佬的指点后,我打开了新世界的大门找到了新的方法

    例如:1 2 2 2 3
    第1个2对1-2,1-3,1-4,1-5,2-2,2-3,2-4,2-5的不相同值的数量有贡献
    第2个2对3-3,3-4,3-5的不相同值的数量有贡献
    第3个2对4-4,4-5的不相同的值的数量有贡献
    由于每一组a-b,b-a(a<b)只计算了其中的一个(a-b),所以要乘2。
    由于乘2后所有a-a计算2遍,所以要减去n。

     1 #include<cstdio>
     2 typedef long long LL;
     3 //bool exist[1001000];
     4 int last[1001000];
     5 LL ans,n;
     6 int main()
     7 {
     8     LL i,t;
     9     scanf("%lld",&n);
    10     for(i=1;i<=n;i++)
    11     {
    12         scanf("%lld",&t);
    13         ans+=(i-last[t])*(n-i+1);
    14         last[t]=i;
    15         //(last[t]+1)-i,..,(last[t]+1)-n,.....,i-i,..,i-n
    16         //last[t]+1:n-i+1;...i:n-i+1
    17 //        if(exist[t])
    18 //            ans+=n-i+1;
    19 //        else
    20 //        {
    21 //            exist[t]=true;
    22 //            //ans+=i*(n-i+1);
    23 //            //n+(n-1)+...+(n-i+1)
    24 //            ans+=(2*n-i+1)*i/2;
    25 //        }
    26 //错误,无法处理如2 2 4 2的数据
    27     }
    28     printf("%lf",(double)(ans*2-n)/(double)n/(double)n);
    29     return 0;
    30 }
  • 相关阅读:
    Play!:SBT代理设置
    CentOS:Oracle最大连接数问题
    STM32:CooCox IDE环境搭建 点亮LED
    删除con.dat
    几种汉字字体推荐
    Python:print输出中文
    Asp.Net:上传文件
    一梦
    身份证验证规则
    git 进阶
  • 原文地址:https://www.cnblogs.com/hehe54321/p/cf-846f.html
Copyright © 2011-2022 走看看