https://ac.nowcoder.com/acm/contest/874/D
题意:给定长度为 n的数组 A[],B[],将两个数组随机打乱,求 ∑i=1nAiBi的期望值。保留30位小数。
思路:每个位置出现 Ai,Bi的概率是 n21,期望是 n21∗Ai∗Bi,求 sum的话,也就是答案=n1∑i=1nAiBi=n1∗∑Ai∗∑Bi
关键就是保留30位小数。double和long double精度只够15~20位,因此要模拟竖式除法来算,在纸上举个例子就明白了,注意保留每一位数字的也要 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');
}
}