A小红小紫投硬币
题意:小红有n+1枚硬币,小紫有n枚硬币,小红的硬币正面朝上的次数比小紫的硬币正面朝上的次数多的概率是多少
分析:一共有2^(n+1)×2^n次情况,有2^(n+1)×2(n-1)次小红的硬币正面朝上的次数比小紫的硬币正面朝上,所有概率为二分之一
代码:
#include<bits/stdc++.h> using namespace std; int main(){ int a;cin>>a; cout<<"0.500000"<<endl; return 0; }
B小红的字符串
题意:给定一个字符串,判断至少需要几次操作才能变成回文字符串。每次操作可以把字母右移动,变成字母表的下一个字母,特别的,z变成a
分析:判断si变成sn-i-1需要操作几次,从左移到右直接相减,从右到左用26减去从左到右的次数即可。
代码:
#include<bits/stdc++.h> using namespace std; typedef long long ll; int main(){ string s;cin>>s; ll len=s.size(); ll sum=0; for(int i=0;i<len;i++){ if(s[i]!=s[len-i-1]){ if(s[i]-'a'<s[len-i-1]-'a'){ ll c=s[len-i-1]-'a'+1-(s[i]-'a'+1); sum+=min(c,26-c); } } } cout<<sum<<endl; }
C小红的01消除
题意:给定一个字符串,可以进行以下操作:
删除任意一个字串"11","01","00",小红最多能执行操作一x次,操作二y次,操作三z次。问小红最多可以执行多少次操作二。
分析:如果si后面包括本身0的个数小于等于1的个数,那么就可以操作1次,然后消除1个1。
代码:
#include<bits/stdc++.h> using namespace std; typedef long long ll; int main(){ int n;cin>>n; string s;cin>>s; int k1=0,k0=0; int c=0; int x,y,z;cin>>x>>y>>z; for(int i=n-1;i>=0;i--){ if(s[i]=='1')k1++; if(s[i]=='0'){ if(k1>0){ k1--; c++; } } if(c==y)break; } cout<<c<<endl; return 0; }
D小红组比赛
题意:有n场比赛,每场m道题,从每场选一道题,使其组成的难度分数最接近target,求最小值。
分析:dpij表示第i层有难度和为j,用背包存入难度共5000.每层的难度存好了,就可以给下一层
代码:
#include<bits/stdc++.h> using namespace std; int main(){ int n,m;cin>>n>>m; vector<vector<int>>a(n+10,vector<int>(m)); for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ cin>>a[i][j]; } } int target;cin>>target; vector<vector<int>>dp(n+10,vector<int>(5010,0x3f3f3f3f)); dp[1][0]=0; for(int i=1;i<=n+1;i++){ for(int j=1;j<=m;j++){ int dif=a[i][j]; for(int s=5000;s>=dif;s--){ if(dp[i][s-dif]!=0x3f3f3f3f){ dp[i+1][s]=min(dp[i+1][s],s-target); } } } } int ans=0x3f3f3f3f; for(int s=0;s<=5000;s++){ if(dp[n+1][s]!=0x3f3f3f3f){ ans=min(ans,abs(s-target)); } } cout<<ans<<endl; }
E折半丢弃
题意:给定一个数组,每次操作将任意一个数/2向下取整,使得没有出现在数组中的最小非负整数最大。求最大最小非负整数。
分析:用二分找那个最大的没有出现在数组中的最小非负整数,如果有比他更小的vis未被标记的,就将右区间缩小。
代码:
#include<bits/stdc++.h> using namespace std; const int N=1e5+10; int t,n; int a[N]; bool vis[N]; bool check(int x){ memset(vis,0,sizeof vis); for(int i=1;i<=n;i++){ int t=a[i]; while(t&&(t>=x||vis[t]))t/=2; vis[t]=1; } for(int i=0;i<x;i++) if(!vis[i])return false; return true; } int main() { cin>>t; while(t--) { cin>>n; for(int i=1;i<=n;i++)cin>>a[i]; int l=1,r=n; while(l<r) { int mid=l+r+1>>1; if(check(mid))l=mid; else r=mid-1; } cout<<l<<endl; } return 0; }
F小红走矩阵
题意:有个n×m的矩阵,小红位于起点(1,1),想到终点(n,m),每步可以往上下左右空地移动一格。小红可以进行最多一次操作:选择矩阵中的一处障碍替换成空地,代价是失去上下左右四个方向中一个移动的能力。求从起点到终点的最小步数。
分析:用bfs找出最小步数,枚举方向与当前禁止方向一直忽略,遇到墙,如果不能穿就忽略,如果能穿,就改成不能穿了。
代码:
#include<bits/stdc++.h> using namespace std; string a[1002]; bool vis[1001][1001][2][5]; int n,m; int dx[]={1,0,0,-1},dy[]={0,1,-1,0}; struct node{ int x,y,xuan,ban,dis; }; queue<node> q; int main(){ cin>>n>>m; for(int i=0;i<n;i++) cin>>a[i]; q.push({0,0,1,4,0}); q.push({0,0,0,3,0}); q.push({0,0,0,2,0}); q.push({0,0,0,1,0}); q.push({0,0,0,0,0}); vis[0][0][0][0]=1; vis[0][0][0][1]=1; vis[0][0][0][2]=1; vis[0][0][0][3]=1; vis[0][0][1][4]=1; while(!q.empty()){ auto ck=q.front(); q.pop(); if(ck.x==n-1&&ck.y==m-1){ cout<<ck.dis; return 0; } for(int i=0;i<4;i++){ if(ck.ban==i) continue; int x=ck.x+dx[i],y=ck.y+dy[i]; if(x<0||x>=n||y<0||y>=m) continue; if(vis[x][y][ck.xuan][ck.ban]) continue; if(a[x][y]=='X'&&ck.xuan==1) continue; if(a[x][y]=='X'){ q.push({x,y,1,ck.ban,ck.dis+1}); vis[x][y][1][ck.ban]=1; } else{ q.push({x,y,ck.xuan,ck.ban,ck.dis+1}); vis[x][y][ck.xuan][ck.ban]=1; } } } cout<<-1; }