我包菜的牢底
A DFS搜索
题干
最近,fried-chicken完全学明白了DFS搜索(如上图所示)!于是学弟向他请教DFS搜索,fried-chicken热心的进行了讲解:
所谓DFS搜索,就是给定一个字符串sss,问能否找到sss的一个子序列,使得该子序列的值为 DFS 或 dfs。
请你分别判断字符串sss中是否含有 DFS 子序列与 dfs 子序列。
5
6
dafasa
6
dDFfSs
6
sfdDSF
6
DFSDFS
3
dfs
0 1
1 1
0 0
1 0
0 1
题解:
只要按DFS/dfs的顺序去寻找有没有完整出现过即可
void solve(){
int n;
string s;
cin>>n>>s;
int f1=0,f2=0,f3=0;
for(int i=0;i<n;i++){
if(s[i]=='D') f1=1;
if(s[i]=='F' and f1==1) f2=1;
if(s[i]=='S' and f2==1) f3=1;
}
if(f3) cout<<1<<" ";
else cout<<0<<" ";
f1=0,f2=0,f3=0;
for(int i=0;i<n;i++){
if(s[i]=='d') f1=1;
if(s[i]=='f' and f1==1) f2=1;
if(s[i]=='s' and f2==1) f3=1;
}
if(f3) cout<<1<<" ";
else cout<<0<<" ";
cout<<endl;
}
M 牛客老粉才知道的秘密
签到
题干:
现在,在本次比赛的主页点击"排名",您就会看到本场比赛的榜单,可以看到,榜单中直接列出了本场比赛的所有题目。
现在,作为牛客老粉,炸鸡想用这道题给大家科普一下牛客以前榜单的愚蠢之处:
牛客以前的榜单并不是现在这样,而是至多同时只显示六道题目。同时榜单上还有"向左"按钮与"向右"按钮来切换显示的题目。以"向右"按钮为例,点击一次该按钮会显示接下来的六道题,特别的,如果接下来的六道题超出了总题数,则会将最后一题放到当前显示的最右侧。"向左"按钮同理。
现在,你需要回答,对于nnn道题的一场比赛,显示的六道题目中最左侧的题目一共有几种可能取值。
以下面共n=14道题的情况为例:
题解:
列几组数据之后发现两种情况:1.能被6整除,直接输出n/6 2.不能整除就输出2*(n/6)
void solve(){
int n;
cin>>n;
if(n%6==0){
cout<<n/6<<endl;
}
else{
cout<<(2*(n/6))<<endl;
return ;
}
}
G why买外卖
题干:
题解:
可以用pair<int,int>存放每组输入,再按a[i].first升序排序,再将a[i].second进行一次前缀和,这样就可以保证金额达到a[i].first时可以用的满减券最大。处理完之后直接贪心,如果现有金钱m加上满减券的前缀和大于等于对应的外卖金额,就更新答案。
pII a[N];
void solve(){
int n,m,x,y;
cin>>n>>m;
vector<int>sum(n+1,0);
for(int i=1;i<=n;i++){
cin>>a[i].x>>a[i].y;
}
sort(a+1,a+n+1);
// for(int i=1;i<=n;i++) cout<<a[i].x<<" "<<a[i].y<<endl;
for(int i=1;i<=n;i++){
sum[i]=sum[i-1]+a[i].y;
}
int ans=m;
for(int i=1;i<=n;i++){
if(m+sum[i]>=a[i].x) ans=max(ans,m+sum[i]);
}
cout<<ans<<endl;
}
C 按闹分配
题干:
题解:
依然是前缀和问题,先将该序列升序排列,用前缀和处理一下,所得结果就是对应的人办完事情的时刻,也是每个人的不满意度。用于插队后,鸡后面的每个人不满意度都会+tc(鸡处理事情的时间,总不满意度就是tc*(鸡后面的人数),因此就能得到鸡插队的位置 pos=max(0,n-m/tc)。
最后不要忘记加上本身处理事情的时间tc
void solve(){
int n,q,tc;
cin>>n>>q>>tc;
int t[n+1];
for(int i=1;i<=n;i++) cin>>t[i];
sort(t+1,t+1+n);
int ans[n+1];
ans[0]=0;
for(int i=1;i<=n;i++) ans[i]=ans[i-1]+t[i];
while(q--){
int m;
cin>>m;
int tmp=max(0ll,n-m/tc);
cout<<ans[tmp]+tc<<endl;
}
}
E :本题又主要考察了贪心
题干:
题解:
起初以为是分类讨论,后来发现无法判断当前的队伍在后面会不会还有比赛,再看数据范围可以用dfs,直接dfs。
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N =1e6+10;
const int INF=0x3f3f3f3f;
typedef pair<int, int> pII;
#define x first
#define y second
typedef long long ll;
#define pb push_back
const int mod=1e9+7;
#define endl '\n'
const double eps=1e-5;
int ddx[] = {0,1,3};
int ddy[] = {3,1,0};
int n,m;
int a[N];
pII b[N];
int ans;
void dfs(int u){
if(u>=m){
int cnt=1;
for(int i=2;i<=n;i++){
if(a[i]>a[1]) cnt++;
}
ans=min(ans,cnt);
return ;
}
for(int i=0;i<3;i++){
a[b[u].x]+=ddx[i];
a[b[u].y]+=ddy[i];
dfs(u+1);
a[b[u].x]-=ddx[i];
a[b[u].y]-=ddy[i];
}
}
void solve(){
cin>>n>>m;
ans=n;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=0;i<m;i++) cin>>b[i].x>>b[i].y;
dfs(0);
cout<<ans<<endl;
}
signed main(){
ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);
int T= 1;
cin>>T;
for(int i=1;i<=T;i++){
solve();
}
return 0;
}
L :要有光
题干:
题解:
几何题,把三维的投影成2维即可,答案为3cw
void solve(){
double c,d,w,h;
cin>>c>>d>>h>>w;
cout<<fixed<<setprecision(4)<<3*c*w*1.0<<endl;
}
B 关鸡
题干:
题解:
看鸡的左右两侧有没有被火封死,如果上下两层火的横坐标距离小于等于1的话代表这一侧封死,因此我们考虑以下几种情况
1. 左有火f1
2.右侧被封死 f2
3.左侧被封死 f3
4.右侧被封死f4
5.有特殊点(2,0) f5
但总之ans不可能超过3,因为只要围住鸡周围3格子他就不能动了,根据上述几种情况进行分类讨论即可。在判断是否封死是可以采用双指针方法
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N =1e6+10;
const int INF=0x3f3f3f3f;
typedef pair<int, int> pII;
#define x first
#define y second
typedef long long ll;
#define pb push_back
const int mod=1e9+7;
#define endl '\n'
const double eps=1e-5;
int ddx[] = {1,0,0,-1};
int ddy[] = {0,1,-1,0};
void solve(){
vector<int>x1,x2;
int n;
int cnt=0;
bool f1=0,f2=0,f3=0,f4=0,f5=0;//务必务必初始化
cin>>n;
for(int i=0;i<n;i++){
int x,y;
cin>>x>>y;
if(x==1) x1.pb(y);
else x2.pb(y);
if(y<0) f1=1;
else if(y>0)f2=1;
if(x==1 and y==-1) cnt++;
if(x==2 and y==0) cnt++,f5=1;
if(x==1 and y==1) cnt++;
}
int ans=3-cnt;
// cout<<ans<<endl;
sort(x1.begin(),x1.end());
sort(x2.begin(),x2.end());
int j=0;
for(int i=0;i<x1.size();i++){
while(j+1<x2.size() and x1[i]+1>=x2[j+1]) j++;
if(j>=0 and j<x2.size() and abs(x1[i]-x2[j])<=1){
if(x1[i]<0) f3=1;
else f4=1;
}
}
//双指针找纵坐标不同但横坐标小于1的点
//下面分类
// cout<<f1<<" "<<f2<<" "<<f3<<" "<<f4<<" "<<f5<<endl;
if(f3 and f4){
cout<<0<<endl;
}
else if(f3 and !f4){
if(f5) cout<<min(1ll,ans)<<endl;
else{
if(f2) cout<<min(1ll,ans)<<endl;
else cout<<min(2ll,ans)<<endl;
}
}
else if(!f3 and f4){
if(f5) cout<<min(1ll,ans)<<endl;
else{
if(f1) cout<<min(1ll,ans)<<endl;
else cout<<min(2ll,ans)<<endl;
}
}
else{
if(f1 and f2) cout<<min(2ll,ans)<<endl;
else cout<<min(3ll,ans)<<endl;
}
}
signed main(){
ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);
int T= 1;
cin>>T;
for(int i=1;i<=T;i++){
solve();
}
return 0;
}
I It's bertrand paradox. Again!
题干:
判断作业
两人的方法不同就在于前者的x,y一经确定就不修改,因此可以知道前者的半径期望一定小于后者,因此我们只算出找到两者半径r的期望值,再进行判断即可。
这边算出二者期望值
#include<bits/stdc++.h>
using namespace std;
int main() {
default_random_engine e;
uniform_int_distribution<int> u1(-99,99); // 左闭右闭区间
uniform_int_distribution<int> u2(1,100);
e.seed(time(0));
int n=1e5;
double r1=0;
for(int i=1;i<=n;i++){
int x=u1(e),y=u1(e);
while(1){
int r=u2(e);
if(x+r>100 or x-r<-100 or y+r>100 or y-r<-100){
continue;
}
else{
r1+=r;
break;
}
}
}
double r2=0;
for(int i=1;i<=n;i++){
while(1){
int x=u1(e),y=u1(e);
int r=u2(e);
if(x+r>100 or x-r<-100 or y+r>100 or y-r<-100){
continue;
}
else{
r2+=r;
break;
}
}
}
cout<<r1/n<<" "<<r2/n<<endl;
}
r1=17.3742 r2=25.5075
算出期望值之后我们选定一个判断值,这个值只要在上面两个期望值中间取即可,我取了20,代码如下
void solve(){
double sum,n;
cin>>n;
for(int i=1;i<=n;i++){
int x,y,r;
cin>>x>>y>>r;
sum+=r;
}
if(sum/n<20) cout<<"bit-noob";
else cout<<"buaa-noob";
}
其他的之后再补