2019华工软院E. HRY and array

https://ac.nowcoder.com/acm/contest/874/D

题意:给定长度为 n n n的数组 A [ ] , B [ ] A[],B[] A[],B[],将两个数组随机打乱,求 ∑ i = 1 n A i B i \sum_{i=1}^nA_iB_i i=1nAiBi的期望值。保留30位小数。
思路:每个位置出现 A i , B i A_i,B_i Ai,Bi的概率是 1 n 2 \frac{1}{n^2} n21,期望是 1 n 2 ∗ A i ∗ B i \frac{1}{n^2}*A_i*B_i n21AiBi,求 s u m 的 话 , 也 就 是 答 案 = 1 n ∑ i = 1 n A i B i = 1 n ∗ ∑ A i ∗ ∑ B i sum的话,也就是答案=\frac1{n}\sum_{i=1}^nA_iB_i=\frac1{n}*\sum{A_i}*\sum{B_i} sum=n1i=1nAiBi=n1AiBi
关键就是保留30位小数。double和long double精度只够15~20位,因此要模拟竖式除法来算,在纸上举个例子就明白了,注意保留每一位数字的也要 l l ll ll,因为整数位可能很大,而小数位只是0 ~ 9。

//华工软院E
#include<bits/stdc++.h>
using namespace std;
#define ll long long

int T,n;
ll s1,s2,s;
ll num[40];

int main()
{
   // freopen("input.in","r",stdin);
    cin>>T;
    while(T--)
    {
        cin>>n;
        int x;
        s1=s2=0;
        for(int i=1;i<=n;i++)scanf("%d",&x),s1+=x;
        for(int i=1;i<=n;i++)scanf("%d",&x),s2+=x;
        ll s=s1*s2;
        num[0]=s/n;
        for(int i=1;i<=31;i++)
        {
            s=s%n*10;
            num[i]=s/n;
        }
        if(num[31]>=5)num[30]++;
        int p=30;
        while(p>0&&num[p]==10){num[p-1]++;num[p]=0;p--;}
        printf("%lld.",num[0]);
        for(int i=1;i<=30;i++)printf("%lld",num[i]);
        putchar('\n');
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值