题意:
三个面都是直角的三棱锥,三个棱长分别为 a , b , c a,b,c a,b,c(在 [ 1 , n ] [1,n] [1,n]中任取)。设顶点到底面的距离 h h h,求 1 h 2 \frac{1}{h^2} h21的期望。
解析:
我看官方讲解推导实在太麻烦了,于是写一下这篇博客说一下自己的推法。
既然三棱锥三个角都是直角,我们直接把顶点当作坐标原点,三条棱当作三个方向的轴, h h h的求解就转换成了点到面的距离。
三维直角坐标系中点 ( x 0 , y 0 , z 0 ) (x_0,y_0,z_0) (x0,y0,z0)到面 A x + B y + C z + D = 0 Ax+By+Cz+D=0 Ax+By+Cz+D=0的距离公式:
h = ∣ A x 0 + B y 0 + C z 0 + D ∣ A 2 + B 2 + C 2 h=\frac{|Ax_0+By_0+Cz_0+D|}{\sqrt{A^2+B^2+C^2}} h=A2+B2+C2∣Ax0+By0+Cz0+D∣
底面是一个过 ( 0 , 0 , a ) , ( b , 0 , 0 ) , ( 0 , c , 0 ) (0,0,a),(b,0,0),(0,c,0) (0,0,a),(b,0,0),(0,c,0)的面,面的公式求都不用求
a c x + a b y + b c z − a b c = 0 ac\ x+ab\ y+bc\ z-abc=0 ac x+ab y+bc z−abc=0
顶点是坐标原点,直接套公式
h = a b c a 2 b 2 + b 2 c 2 + a 2 c 2 h=\frac{abc}{a^2b^2+b^2c^2+a^2c^2} h=a2b2+b2c2+a2c2abc
那么
1 h 2 = 1 a 2 + 1 b 2 + 1 c 2 \frac{1}{h^2}=\frac{1}{a^2}+\frac{1}{b^2}+\frac{1}{c^2} h21=a21+b21+c21
a , b , c a,b,c a,b,c等价, E ( 1 h 2 ) = 3 × E ( 1 a 2 ) E(\frac{1}{h^2})=3\times E(\frac{1}{a^2}) E(h21)=3×E(a21)
线性求下逆元,再求前缀和,最后输出的时候别忘了期望还要除以概率, p r e [ n ] × i n v [ n ] % m o d pre[n]\times inv[n]\%mod pre[n]×inv[n]%mod
AC代码:
#include<cstdio>
#include <cmath>
#define pb push_back
#define fir first
#define sec second
#define ms(a,b) memset(a,b,sizeof(a))
#define INF 0x3f3f3f3f
#define sp system("pause")
#define multi int T;scanf("%d",&T);while(T--)
using namespace std;
typedef long long ll;
typedef double db;
const int N=6e6+5;
const ll mod=998244353;
const db pi=acos(-1.0);
ll inv[N],pre[N];
ll qpow(ll a,ll b){
ll res=1;
while(b){
if(b&1) res=res*a%mod;
a=a*a%mod;
b>>=1;
}
return res;
}
void invv(int n,int p)//1~n在模p意义下逆元
{
inv[0]=inv[1]=1;
for(int i=2;i<=n;i++)
inv[i]=((-p/i*inv[p%i])%p+p)%p;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("D:\\work\\data.in","r",stdin);
#endif
invv(6e6,mod);
for(ll i=1;i<=6e6;i++){
pre[i]=(pre[i-1]+3*inv[i]*inv[i])%mod;
}
multi{
int n;
scanf("%d",&n);
printf("%lld\n",pre[n]*inv[n]%mod);
}
}