牛客练习赛46,A(数学)B(前缀和+二分)C(概率期望+矩阵快速幂)

Contest:https://ac.nowcoder.com/acm/contest/894#question

A-华华教奕奕写几何(数学)

题目链接:https://ac.nowcoder.com/acm/contest/894/A

题目大意:中文题。

思路:得到公式,联立:S=((r1+r2)^2-(\frac{r1}{2})^2-(\frac{r2}{2})^2)*PI,求R=r1+r2的最小值。

经过一堆化简得:r1*r2=\frac{S}{PI},然后想到对勾函数,然后得到r1=r2=R/2;所以得:R=\sqrt{\frac{S}{PI}}*2

ACCode:

int main(){
	double S;
	while(~scanf("%lf",&S)){
		printf("%.3lf\n",sqrt(S/PI)*2.0);
	}
	
}

B-华华送奕奕小礼物(前缀和+二分)

题目链接:https://ac.nowcoder.com/acm/contest/894/B

题目大意:中文题

思路:由于该矩阵的特殊构造,可以将矩阵(x1,y1)~(x2,y2)的和写成(PreA[x2]-PreA[x1-1])*(PreB[y2]-PreB[y1-1])形式;

对于所有的矩阵,都存在x2>=x1&&y2>=y1,由于x,y相互独立,因此处理出来每个y的情况,对于每种x,二分得到y的可行范围。

ACCode:

//#pragma comment(linker, "/STACK:1024000000,1024000000")
  
#include<stdio.h>
#include<string.h> 
#include<math.h> 
   
#include<map>  
#include<set>
#include<deque> 
#include<queue> 
#include<stack> 
#include<bitset>
#include<string> 
#include<fstream>
#include<iostream> 
#include<algorithm> 
using namespace std; 
  
#define ll long long 
#define Pair pair<int,int>
//#define max(a,b) (a)>(b)?(a):(b)
//#define min(a,b) (a)<(b)?(a):(b)
#define clean(a,b) memset(a,b,sizeof(a))// ??
//std::ios::sync_with_stdio(false);
//  register
const int MAXN=1e3+10;
const int INF32=0x3f3f3f3f;
const ll INF64=0x3f3f3f3f3f3f3f3f;
const ll mod=1e9+7;
const double PI=acos(-1.0);
const double EPS=1.0e-8;

ll A[MAXN],B[MAXN];
ll PreA[MAXN],PreB[MAXN];
ll Res[MAXN*MAXN],tot;
int n,m;
ll L,R;

int Cmp(ll a,ll b){
	return a<b;
}
int FindL(ll Key){
	int l=1,r=tot,mid;
	while(l<=r){
		mid=(l+r)>>1;
		if(Key*Res[mid]<L) l=mid+1;
		else r=mid-1;
	}return l;
}
int FindR(ll Key){
	int l=1,r=tot,mid;
	while(l<=r){
		mid=(l+r)>>1;
		if(Key*Res[mid]>R) r=mid-1;
		else l=mid+1;
	}return r;
}
int FindAns(ll Key){
	int l=FindL(Key),r=FindR(Key);
	return r-l+1;
}
int main(){//(x1,y1)~(x2,y2)=PreA[x2]-PreA[x1-1])*(PreB[y2]-PreB[y1-1];
	while(~scanf("%d%d%lld%lld",&n,&m,&L,&R)){
		for(int i=1;i<=n;++i) scanf("%lld",&A[i]);
		for(int i=1;i<=m;++i) scanf("%lld",&B[i]);
		for(int i=1;i<=n;++i) PreA[i]=PreA[i-1]+A[i];
		for(int i=1;i<=m;++i) PreB[i]=PreB[i-1]+B[i];
		tot=0;
		for(int i=1;i<=m;++i){
			for(int j=i;j<=m;++j){
				Res[++tot]=PreB[j]-PreB[i-1];
			}
		}
		sort(Res+1,Res+1+tot,Cmp);
		ll ans=0;
		for(int i=1;i<=n;++i){
			for(int j=i;j<=n;++j){
				ans+=FindAns(PreA[j]-PreA[i-1]);
			}
		}printf("%lld\n",ans);
	}
}

C-华华跟奕奕玩游戏

题目链接:https://ac.nowcoder.com/acm/contest/894/C

题目大意:中文题

思路:总共有四种情况,放入黑球拿黑球,放入黑球那篮球,放入篮球拿黑球,放入篮球那篮球。

ans=\sum_{i=1}^{4} a*f[i].然后得到式子:

黑球的概率:ans1=[\frac{a[i]+1}{n+m+1}*a[i]+\frac{n+m+1-(a[i]+1)}{n+m+1}*(a[i]+1)]*p

篮球的概率:ans2=[\frac{n+m-a[i]+1}{n+m+1}*(a[i]-1)+\frac{a[i]}{n+m+1}*a[i]]*p

然后a[i+1]=ans1+ans2.最后得出化简得到式子:a[i+1]=\frac{n+m}{n+m+1}*p+\frac{n+m}{m+n+1}*a[i]

发现一个递推式,可以使用矩阵快速幂,构造矩阵:A*\begin{bmatrix} a[i] \\ p \end{bmatrix}=\begin{bmatrix} a[i+1] \\ p \end{bmatrix}.

A=\begin{bmatrix} \frac{n+m}{n+m+1} \ \frac{n+m}{n+m+1} \\ 0 \ 1 \end{bmatrix}。最后由于要输出a/b%mod所以在前面求逆元之后再相乘即可。

ACCode:

//#pragma comment(linker, "/STACK:1024000000,1024000000")
  
#include<stdio.h>
#include<string.h> 
#include<math.h> 
   
#include<map>  
#include<set>
#include<deque> 
#include<queue> 
#include<stack> 
#include<bitset>
#include<string> 
#include<fstream>
#include<iostream> 
#include<algorithm> 
using namespace std; 
  
#define ll long long 
#define Pair pair<int,int>
//#define max(a,b) (a)>(b)?(a):(b)
//#define min(a,b) (a)<(b)?(a):(b)
#define clean(a,b) memset(a,b,sizeof(a))// ??
//std::ios::sync_with_stdio(false);
//  register
const int MAXN=1e3+10;
const int INF32=0x3f3f3f3f;
const ll INF64=0x3f3f3f3f3f3f3f3f;
const ll mod=1e9+7;
const double PI=acos(-1.0);
const double EPS=1.0e-8;

ll GCD(ll a,ll b){return b==0?a:(GCD(b,a%b));}

struct Matrix{
	ll Mat[5][5];
	friend Matrix operator * (Matrix a,Matrix b){
		ll temp[5][5];clean(temp,0);
		for(int i=1;i<=2;++i){
			for(int j=1;j<=2;++j){
				for(int k=1;k<=2;++k){
					temp[i][j]+=(a.Mat[i][k]*b.Mat[k][j]);
					temp[i][j]=temp[i][j]%mod;
				}
			}
		}
		Matrix Ans;
		for(int i=1;i<=2;++i){
			for(int j=1;j<=2;++j){
				Ans.Mat[i][j]=temp[i][j];
			}
		}return Ans;
	}
};
ll n,m,k,a,b;

Matrix Quick(Matrix a,int n){
	Matrix temp;
	temp.Mat[1][1]=temp.Mat[2][2]=1;
	temp.Mat[1][2]=temp.Mat[2][1]=0;
	while(n){
		if(n&1) temp=temp*a;
		a=a*a;
		n=n>>1;
	}return temp;
}
ll GetB(ll a,ll n){
	ll temp=1;
	while(n){
		if(n&1) temp=temp*a%mod;
		a=a*a%mod;
		n=n>>1;
	}return temp;
}
int main(){
	scanf("%lld%lld%lld%lld%lld",&n,&m,&k,&a,&b);
	Matrix A;
	A.Mat[1][1]=(n+m)*GetB(n+m+1,mod-2)%mod;
	A.Mat[1][2]=A.Mat[1][1]*(a*GetB(b,mod-2)%mod)%mod;
	A.Mat[2][1]=0,A.Mat[2][2]=1;
	A=Quick(A,k);
	ll ans=(n*A.Mat[1][1]%mod+A.Mat[1][2])%mod;
	printf("%lld\n",ans);
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值