目录
A - Hamburgers
题目链接:
HRBU 2021年暑期训练阶段四Day1 - Virtual Judge
题意:
给定一个字符串,这表示一个汉堡的配方,接着在给定两个数组第一个数组代表现在有的配料,从左到右依次是B,S,C的个数,第二个则代表每一个配料的单价,最后给定一个你已有的金额,问最多能做多少个汉堡
做法:
既然要求汉堡的个数,那咱们不如就以汉堡的个数作为一个二分的结果,如果汉堡的个数所需要的的配料钱大于已有金额,那就移动上限,否则就移动下限,这就是一个二分答案的思路,需要注意的是,计算每一个配料所需金额时,要是某一个配料小于0了,就直接置零,否则会影响结果的判断
#include<iostream> #include<algorithm> #include<cstdio> #include<cstring> #include<string> #include<string.h> #include<cstdlib> #include<fstream> #include<queue> #include<stack> #include<map> #include<set> #include<iomanip> #define Pi acos(-1.0) #define inf 2000000000000 using namespace std; typedef long long ll; const ll maxn=1e6+10; int b,s,c; string Str; int nb,ns,nc,pb,ps,pc; ll mon; bool judge(ll n) { ll cb,cs,cc; cb=(n*b-nb)*pb; cs=(n*s-ns)*ps; cc=(n*c-nc)*pc; if(cb<0) cb=0; if(cs<0) cs=0; if(cc<0) cc=0; if(cb+cs+cc<=mon) return 1; return 0; } int main() { while(cin>>Str) { b=s=c=0; int len=Str.size(); for(int i=0;i<len;i++) { if(Str[i]=='B') b++; if(Str[i]=='S') s++; if(Str[i]=='C') c++; } cin>>nb>>ns>>nc; cin>>pb>>ps>>pc; cin>>mon; ll l=1,r=inf,mid; while(l<r) { mid=(l+r)/2; if(judge(mid)) l=mid+1; else r=mid; } cout<<l-1<<endl; } return 0; } /** */
B - River Hopscotch
题目链接:
HRBU 2021年暑期训练阶段四Day1 - Virtual Judge
题意:
一群牛牛在河上蹦跶,要从一个石头蹦跶到另一个石头,作为起点和终点的两个石头相差L,且这之间有N块石头,每一块石头到达起点的距离为Di,有一个农夫想要增加这些石头之间的最小距离,问他最少需要挪走几块石头才能使最小距离最大化捏(石头数量小于等于M)
做法:
典型的最小值最大化问题,构思一下,要使最小值最大化,在二分查找的同时去贪心的判断这个值是否满足条件,要是不满足那说明上限需要下移,若是满足,那我们是否可以让这个值稍微在更大一丢丢,判断是否还继续满足条件呢?以此类推
#include<iostream> #include<algorithm> #include<cstdio> #include<cstring> #include<string> #include<string.h> #include<cstdlib> #include<fstream> #include<queue> #include<stack> #include<map> #include<set> #include<iomanip> #define Pi acos(-1.0) #define inf 1000000010 using namespace std; typedef long long ll; const int maxn=1e5+10; int L,N,M; ll D[maxn]; bool judge(ll num) { int cnt=1,tmp=D[0]; for(int i=1;i<=N+1;i++) { if(D[i]-tmp>=num) cnt++,tmp=D[i]; if(cnt>=M) return true; } return false; } void slove() { ll l=0,r=inf,mid; while(r-l>1) { mid=(l+r)/2; if(judge(mid)) l=mid; else r=mid; } cout<<l<<endl; } int main() { ios::sync_with_stdio(false); while(cin>>L>>N>>M) { for(int i=1;i<=N;i++) cin>>D[i]; D[0]=0; D[N+1]=L; sort(D,D+N+2); M=N+2-M; slove(); } return 0; } /** */
C - Cup
题目链接:
HRBU 2021年暑期训练阶段四Day1 - Virtual Judge
题意:
给定一个杯子的底面半径,杯口半径,杯子高度以及水的体积,问杯子中水的高度
做法:
图示:
如图所示,是我们要求解的一个水杯的截面图,其中 h 就是我们需要求解的答案,根据相似三角形的性质(初中数学知识)推导出公式
这里我们就能得出有关于我们需要求的高度和已知量的一个联系,接着我们就去二分这个高度即可,需要注意的是这个水杯是一个圆台的形状,其中的水也是一个圆台的形状,所以求解时还需要用到圆台的体积公式 (1/3)*Pi*h*(R^2+R*r+r^2)
#include<iostream> #include<algorithm> #include<cstdio> #include<cstring> #include<string> #include<string.h> #include<cstdlib> #include<fstream> #include<queue> #include<stack> #include<map> #include<set> #include<iomanip> #define Pi acos(-1.0) #define inf 2000000000000 using namespace std; typedef long long ll; const ll maxn=1e6+10; double fun(double x,double r,double R,double H) { double u=r+x*(R-r)/H;//返回水面半径 return Pi/3.0*x*(u*u+r*r+u*r);//返回圆台体积 } int main() { double r,R,H; ll V; int T; scanf("%d",&T); while(T--) { scanf("%lf%lf%lf%lld",&r,&R,&H,&V); double bottom=0,top=100,mid; while(top-bottom>1e-10)//最小1e-7 { mid=(top+bottom)/2.0; if(fun(mid,r,R,H)>V) top=mid; else bottom=mid; } printf("%.6lf\n",mid); } return 0; } /** 圆台体积公式:(1/3)*Pi*h*(R^2+R*r+r^2) 水的半径:(rr-r)/R-r=mid/H --> rr=((R-r)*mid)/H+r */
D - Fibonacci
题目链接:
HRBU 2021年暑期训练阶段四Day1 - Virtual Judge
题意:
给定斐波那契矩阵的计算方法,需要你求出第N位斐波那契数的后四位数字是多少
做法:
矩阵快速幂的模板题。矩阵快速幂
这是我的矩阵快速幂的入门板子
//我自己的板子 const ll N=101;/*自己选择*/ struct Node { ll m[N][N]; Node() { memset(m,0,sizeof(m)); } }; Node s,e; Node multi(Node x,Node y)//x为行数组(用行去进行乘积)y为列数组(用列去进行乘积) { Node c; for(int i=0;i<n;i++)//下标看从哪里开始存 for(int j=0;j<n;j++) for(int k=0;k<n;k++) c.m[i][j]=c.m[i][j]%mod+x.m[i][k]*y.m[k][j]%mod; } Node qmi(Node x,ll n)//以快速幂的方式优化矩阵乘积防止超过数据范围 { Node ans=e; while(n) { if(n&1) ans=multi(res,x); x=multi(x,x); n>>=1; } return ans; }
#include<iostream> #include<algorithm> #include<cstdio> #include<cstring> #include<string> #include<string.h> #include<cstdlib> #include<fstream> #include<queue> #include<stack> #include<map> #include<set> #include<iomanip> #define Pi acos(-1.0) #define inf 2000000000000 using namespace std; typedef long long ll; const ll N=2;/*自己选择*/ const int mod=1e4; struct Node { ll m[N][N]; Node() { memset(m,0,sizeof(m)); } }; Node multi(Node x,Node y)//x为行数组(用行去进行乘积)y为列数组(用列去进行乘积) { Node c; for(int i=0; i<N; i++) //下标看从哪里开始存 for(int j=0; j<N; j++) for(int k=0; k<N; k++) c.m[i][j]=(c.m[i][j]+x.m[i][k]*y.m[k][j])%mod; return c; } Node qmi(Node x,ll n)//以快速幂的方式优化矩阵乘积防止超过数据范围 { Node ans; for(int i=0; i<N; i++) ans.m[i][i] = 1; while(n) { if(n&1) ans=multi(ans,x); x=multi(x,x); n>>=1; } return ans; } int main() { ios::sync_with_stdio(false); ll n; while(cin>>n&&n>=0) { if(!n) cout<<0<<endl; else { Node s; s.m[0][1]=s.m[1][0]=s.m[0][0]=1; Node ans=qmi(s,n); //cout<<ans.m[0][0]<<endl; cout<<ans.m[0][1]<<endl; //cout<<ans.m[1][0]<<endl; //cout<<ans.m[1][1]<<endl; } } return 0; } /** */
E - Dating with girls(1)
题目链接:
HRBU 2021年暑期训练阶段四Day1 - Virtual Judge
题意:
给你n个正整数和一个整数k,你需要计算方程x + y = k有多少个不同的解。X和y必须在给定的n个整数中。当x0 != x1或y0 != y1时,两个解是不同的。
做法:
整个map就能搞了,正常的解方程就完了
#include<iostream> #include<algorithm> #include<cstdio> #include<cstring> #include<string> #include<string.h> #include<cstdlib> #include<fstream> #include<queue> #include<stack> #include<map> #include<set> #include<iomanip> #define Pi acos(-1.0) #define inf 1000000010 using namespace std; typedef long long ll; const int maxn=1e5+10; int T,n,k; int y[maxn],ans; void slove() { memset(y,0,sizeof(y)); int len=0; ans=0; map<int,int> mp; cin>>n>>k; for(int i=1;i<=n;i++) { int x; cin>>x; if(mp[x]!=1) { mp[x]=1; y[len++]=x; } } for(int i=0;i<len;i++) { if(mp[k-y[i]]==1) ans++; } cout<<ans<<endl; } int main() { ios::sync_with_stdio(false); cin>>T; while(T--) { slove(); } return 0; } /** */
F - Median
题目链接:
HRBU 2021年暑期训练阶段四Day1 - Virtual Judge
题意:
给定N个数字,X1, X2,…, XN,让我们计算每一对数的差值:∣Xi - Xj∣(1≤i < j≤N)。通过这项工作,我们可以得到C(N,2)差值,现在你的任务是尽快找到差值的中值!
注意,在这个问题中,中值定义为(m/2)-如果差的数量m是偶数。例如,在m = 6的情况下,你必须找到第三小的那个。
做法:
简单的二分,具体样例解释代码下边有。
#include<iostream> #include<algorithm> #include<cstdio> #include<cstring> #include<string> #include<string.h> #include<cstdlib> #include<fstream> #include<queue> #include<stack> #include<map> #include<set> #include<iomanip> #define Pi acos(-1.0) #define inf 2000000000000 using namespace std; typedef long long ll; const int maxn=1e5+10; int N,X[maxn]; bool judge(int tmp,ll num) { ll cnt=0; for(int i=0;i<N;i++) cnt+=X+N-lower_bound(X+i+1,X+N,X[i]+tmp); //判断比当前mid的值还要大的差值数有几个 return cnt<=num/2; } int main() { while(~scanf("%d",&N)) { for(int i=0;i<N;i++) scanf("%d",&X[i]); sort(X,X+N); ll num=N*(N-1)/2; int l=0,r=(X[N-1]-X[0]); while(r-l>1) { int mid=(l+r)/2; if(judge(mid,num)) r=mid; else l=mid; } printf("%d\n",l); } return 0; } /** 1 3 2 4 1:2 1 3 3:2 1 1 2:1 1 2 4:3 1 2 1 2 3 1 1 2 2 1 1 3 2 1 1 1 1 1 1 1 2 2 2 2 3 3 1 1 10 2 9 1 9 8 1 8 1 1 8 8 9 9 */
G - sort
题目链接:
HRBU 2021年暑期训练阶段四Day1 - Virtual Judge
做法:
限制输入!!!!
#include<iostream> #include<algorithm> #include<cstdio> #include<cstring> #include<string> #include<string.h> #include<cstdlib> #include<fstream> #include<queue> #include<stack> #include<map> #include<set> #include<iomanip> #define Pi acos(-1.0) using namespace std; typedef long long ll; const ll maxn=1e6+10; int n,m; int a[maxn]; int main() { while(~scanf("%d%d",&n,&m)) { for(int i=1; i<=n; i++) scanf("%d",&a[i]); sort(a+1,a+n+1); printf("%d",a[n]); m--; for(int i=n-1; m>0; m--,i--) printf(" %d",a[i]); printf("\n"); } return 0; } /** */