牛客练习赛46,A(数学)B(前缀和+二分)C(概率期望+矩阵快速幂)
Contest:https://ac.nowcoder.com/acm/contest/894#question
A-华华教奕奕写几何(数学)
题目链接:https://ac.nowcoder.com/acm/contest/894/A
题目大意:中文题。
思路:得到公式,联立:,求R=r1+r2的最小值。
经过一堆化简得:,然后想到对勾函数,然后得到r1=r2=R/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
题目大意:中文题
思路:总共有四种情况,放入黑球拿黑球,放入黑球那篮球,放入篮球拿黑球,放入篮球那篮球。
即.然后得到式子:
黑球的概率:
篮球的概率:
然后a[i+1]=ans1+ans2.最后得出化简得到式子:
发现一个递推式,可以使用矩阵快速幂,构造矩阵:.
。最后由于要输出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);
}