20240221寒假单元测验题解
wflengxuenong · · 个人记录
T316849 人数
考察最值、排序等。可以用最值,也可以用sort、桶排序等。
T311007 优秀的码字
本题考察枚举及其优化。
枚举:枚举第
如何优化?
-
当出现小于
k 的距离,立即退出。 -
数学优化。在
60% 数据基础上另有40% 的数据N>2^m 根据鸽笼原理,那么必然有两个相同的字符。一定不符合要求。
参考代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn=222;
string ss[maxn];
int main()
{
int N,M,K;scanf("%d%d%d",&N,&M,&K);
if(N>(1LL<<M))return puts("No"),0;
for(int i=1;i<=N;++i) cin>>ss[i];
sort(ss+1,ss+1+N);//排序可以找出更近的符号。
for(int i=1;i<=N;++i)
{
int dis=0,j=i+1;
for(int k=0;k<M;++k)if(ss[i][k]!=ss[j][k]) ++dis;
if(dis<K) return puts("No"),0;
}
for(int i=1;i<=N;++i)
for(int j=i+2;j<=N;++j)
{
int dis=0;
for(int k=0;k<M;++k)if(ss[i][k]!=ss[j][k]) ++dis;
if(dis<K) return puts("No"),0;
}
return puts("Yes"),0;
}
T3 挑战赛
考察内容:排序+贪心。 什么情况下一个人能拍到榜首呢?
自己先拿到最高分,让后其余的选手得分尽量低。
其他选手怎样得分尽量低呢?
初始条件为
参考代码:
#include<iostream>
#include<cstdio>
using namespace std;
int n,f[5010][5010],len;
void add(int k) { //高精加法
for(int i=1; i<=len; i++)//两数相加
f[k][i]=f[k-1][i]+f[k-2][i]+f[k-3][i];
for(int i=1; i<=len; i++) { //进位
f[k][i+1]+=f[k][i]/10;
f[k][i]%=10;
}
if(f[k][len+1]>0)len++;
}
int main() {
cin>>n;
len=1;
f[1][1]=1;//预处理
f[2][1]=2;//预处理
f[3][1]=4;
for(int i=4; i<=n; i++)//开始计算
add(i);
for(int j=len; j>=1; j--)//输出
cout<<f[n][j];
cout<<endl;
return 0;
}
T316902 分糖果
本题的要求最大值最小,二分答案的标志性名次。那么分析本题具有单调性吗?
根据题意,小朋友们得到的糖果数越平均越好。蛀牙值越大,每个小朋友分的糖果数越多,分的份数就越少。否则越多。
我们二分蛀牙值,如果分完后糖果有剩余,就还要增大;如果不够分的,就要缩小。
参考代码:
#include <iostream>
using namespace std;
long long n,m,l=1,r,ans;
long long a[300010];
bool check(long long x){ //x 是当前的蛀牙值
long long sum=0;
for(int i=1;i<=m;i++) sum+=(a[i]+x-1)/x;
return sum<=n;
}
int main(){
cin>>n>>m;
for(int i=1;i<=m;i++){cin>>a[i];r+=a[i];} //mid 的极限是总共的球数
while(l<r){ //二分模板
long long mid=(l+r)/2+1;
if(check(mid)){r=mid-1;ans=mid;}
else l=mid;
}
cout<<ans;
return 0;
}
T310718 花园
本题考察了结构体和集合的容斥。
要处理重合的部分
我们给定了矩形的对角线的两个端点,但没有说明大小,要统一为左上角和右下角,然后,找到交集部分。
如何找到交集部分?共有四个横坐标,四个纵坐标,找到中间的两个。
参考代码:
#include <iostream>
#include <iomanip>
#include<stdio.h>
using namespace std;
typedef long long ll;
struct node{//左上角 和右下角
ll xa,ya,xb,yb;
}jx1,jx2,jx3;
int n;
node le_ri(){
node t;
cin>>t.xa>>t.ya>>t.xb>>t.yb;
if(t.xa>t.xb)swap(t.xa,t.xb);
if(t.ya>t.yb)swap(t.ya,t.yb);
return t;
}
ll s(node t){
return (t.xb-t.xa)*(t.yb-t.ya);
}
int main()
{
cin>>n;
jx1=le_ri();
if(n==1){
cout<<s(jx1)<<endl;
return 0;
}
jx2=le_ri();
if(jx1.xa>=jx2.xb||jx1.xb<=jx2.xa||jx1.ya>=jx2.yb||jx1.yb<=jx2.ya) {//2在1的左侧,右侧,下侧,上侧
cout<<s(jx1)+s(jx2)<<endl;
return 0;
}
//相交的情况
jx3.xa=max(jx1.xa,jx2.xa);
jx3.xb=min(jx1.xb,jx2.xb);
jx3.ya=max(jx1.ya,jx2.ya);
jx3.yb=min(jx1.yb,jx2.yb);
cout<<s(jx1)+s(jx2)-s(jx3)<<endl;
}