太阳轰炸(lucas,二项分布)2020CCPC河南省赛I

背景:阿塔尼斯,达拉姆的大主教,在艾尔又一次沦陷之后指挥着星灵的最后一艘方舟舰:亚顿之矛。作为艾尔星灵数千年来的智慧结晶,亚顿之矛除了搭载了以太阳能碎片为核心的兵工厂之外,还配备了诸如汇聚射线、太阳能射线枪等威力强大的支援武器。而在这些武器中,最负盛名、也最让敌人胆寒的就是太阳轰炸。

 

太阳轰炸是一件威力巨大的对星球武器。在太阳轰炸开火时,亚顿之矛将聚集太阳能核心中的太阳能量,向目标坐标发射成百上千枚火焰飞弹。虽然这些火焰飞弹精准度较差,但太阳轰炸的高攻击频率仍然可以让地面上的敌人无法躲避,化为灰烬。

在这一次的行动中,阿塔尼斯的目标是一枚臭名昭著的虚空碎片。在俯视视角下,虚空碎片的投影是一个半径为 R1 的圆,太阳轰炸的攻击散布范围是一个半径为 R2 的圆。这两个圆的圆心均为原点 (0, 0)。太阳轰炸将射出 n 枚火焰飞弹,每一枚火焰飞弹等概率地落在攻击散布范围内每一个点上,所有火焰飞弹的落点相互独立。火焰飞弹的伤害范围是以落点为圆心,半径为 r 的圆。若火焰飞弹的伤害范围和虚空碎片的投影相交,则该枚火焰飞弹命中虚空碎片,造成 a 点伤害。若总伤害大于等于 h,则虚空碎片会被摧毁。

摧毁这枚虚空碎片对阿塔尼斯的战略部署非常重要,因此阿塔尼斯想要知道一次太阳轰炸能够摧毁这枚虚空碎片的概率。你需要输出答案对质数 109 + 7 取模的值。

Input

仅一行,包含六个整数 nR1, R2, rah (1 ≤ n ≤ 5 × 106, 1 ≤ R1, R2, r ≤ 108, 1 ≤ a, h ≤ 108),含义见题目描述。

Output

一个整数,表示答案。

Example

input

Copy

3 2 4 1 1 1

output

Copy

636962896

Note

答案对质数 109 + 7 取模的定义:设 M = 109 + 7,可以证明答案可表示为一个既约分数 

,其中 p, q 均为整数且 q 模 M 不余 0。输出满足 0 ≤ x < M 且 x·q ≡ p ± od{M} 的整数 x

上图对应了样例中 R1 = 2, R2 = 4, r = 1 的情况。其中红色的圆是虚空碎片的投影,蓝色的圆是太阳轰炸的攻击范围。A, B, C 是三R2这个圆是攻击范围,

假设:R1是目标,r是导弹的攻击半径,所以恰好不攻击到的范围就是导弹跟目标相切,这个时候距离就是R1 + r,个可能的落点,其中 A, C 命中虚空碎片,而 B 没有命中虚空碎片。

思路:

这个题总共有三种情况;

1: (h-1)/a+1>n,无解,直接输出0;

2:(R1+r)>=R2,就是无论怎么发射都会打在虚空碎片上,直接输出“1”;

3:

 

只要在这个范围以内的

都可以对目标造成伤害,导弹击中目标的概率就是\frac{\left ( R_{1}+r \right )^{2}}{(R_{2})^{2}},但是概率不能超过1,所以跟1取min,利用二项分布,

#include<bits/stdc++.h>
using namespace std;
const int N=5e6+10;
const int mod=1e9+7;
#define int long long
#define lmw ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
int fact[N],infact[N];
int n,r1,r2,r,a,h;
inline int ksm(int x,int y){
	x%=mod;
	int res=1;
	while(y){
		if(y&1) res=res*x%mod;
		x=x*x%mod;
		y/=2;
	}
	return res%mod;
}
inline int C(int a,int b){
	return fact[a]*infact[b]%mod*infact[a-b]%mod;
}
int lucas(int a,int b){
	if(a<mod&&b<mod) return C(a,b);
	return C(a%mod,b%mod)*lucas(a/mod,b/mod)%mod;
}
inline void unit(){
	fact[0]=1;
	for(int i=1;i<=n;i++){
		fact[i]=fact[i-1]*i%mod;
	}
	infact[n]=ksm(fact[n],mod-2);
	for(int i=n-1;i>=0;i--){
		infact[i]=infact[i+1]*(i+1)%mod;
	}
}
signed main(){
	lmw;
	cin>>n>>r1>>r2>>r>>a>>h;
//	cin>>n;
	unit();
//	infact[5000000]=ksm(fact[5000000],mod-2)%mod;
//	for(int i=4999999;i>=0;i--){
//		infact[i]=infact[i+1]*(i+1)%mod;
//	}
//	cout<<infact[25]<<"\n";
	int op=(h-1)/a+1;
//	if(h%a!=0) op++;
	if(n<op){
		cout<<"0\n";
		return 0;
	}
	else if(r1+r>=r2){
		cout<<"1\n";
		return 0;
	}
	int p=(r1+r)*(r1+r)%mod*ksm(r2*r2,mod-2)%mod;
	int q=(r2*r2%mod-(r1+r)*(r1+r)%mod+mod)%mod*ksm(r2*r2,mod-2)%mod;
	int pp=ksm(p,op);
	int qq=ksm(q,n-op);
	int sum=0;
	for(int i=op;i<=n;i++){
//		sum=(sum+infact[i]*ksm(r1+r,i*2)%mod*ksm((r2*r2-(r1+r)*(r1+r)+mod)%mod,(n-i)))%mod;
		sum=(sum+C(n,i)*pp%mod*qq%mod)%mod;
		pp=pp*p%mod;
		qq=qq*ksm(q,mod-2)%mod;
	}
//	int m=ksm(r2*r2%mod,n)%mod;
	cout<<sum<<"\n";
}

枚举导弹击中的次数,算一下概率就可以了。

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值