问题 A: Welcome Freshmen
时间限制: 1 Sec 内存限制: 128 MB题意:
大一:freshman,大二:sophomore, 大三:junior,大四:senior。根据输入整数,输出英文大学几年级。
解析:
可以直接用if语句,也可以先存在字符数组里面,根据下标输出结果。
主要代码:
void solve() { string s[]={"freshman","sophomore","junior","senior"}; int pos; cin >>pos; cout <<s[pos-1]; }
问题 B: 鳖在这里发电
时间限制: 1 Sec 内存限制: 128 MB题意:
给定一个01串,当0和1相邻时,他们会从序列中删除,并且获得1单位电量,求获得最大电量。
解析:
初次看题会想到直接模拟,当遍历到01或者10时,删除他们并且ans++,但是该过程有点繁琐(用栈实现是最好,这里不给出用栈模拟过程,有兴趣的可以自己学一下栈,然后用栈实现,思路是遇到两个不一样的就弹出栈并且当前电子不放进栈),不妨直接看结果,最后01串中只会剩下0或者1或者为空,因为该串中只有01,他们总会相邻,直到串空或者只剩一种存在时就不会对答案有贡献了。所以只需要输出0和1较少的数量即可。
主要代码:
void solve() { string s; cin >>s; int ans=0; for(int i=0;i<s.size();i++) { if(s[i]=='0') ans++; } cout <<min(ans,(int)s.size()-ans); }
问题 C: 我的书馆
时间限制: 1 Sec 内存限制: 128 MB题意:
现需要拿n本书,已知图书馆有m层,以及每本书的楼层和年份,我们从古至今依次取书,即按照年份大小依次爬楼取书,但是当取书的过程中一旦下楼就必须到1楼再重新上去,下楼的过程中也可以取书。
解析:
这里没有给出排序做法,但其思路本质是一样的,可以自己尝试。
1.可以发现年份的值域并不大,故可以映射到数组中。(也可以排序)
2.记录每个年份对应书籍所在的楼层。(题目保证任意两本书的年代不相同)
3.依次遍历年份大小,模拟取书过程,并记录答案。(注意最后还要到一楼去)
主要代码:
int a[N],b[N],t[N]; void solve() { int n,m,ans=0; cin >>n>>m; for(int i=1;i<=n;i++) { cin >>a[i]>>b[i]; b[i]+=2000; t[b[i]]=a[i]; } int cur=1; for(int i=0;i<=4023;i++) { if(t[i]) { //cout <<t[i]<<" "<<ans<<endl; if(t[i]>=cur) //书在楼上,上楼拿书 { ans+=t[i]-cur; cur=t[i]; }else{ //书在楼下,下楼拿书 ans+=cur-1; int j=i; for(j=i;j<=4023;j++) { if(t[j]) { //cout <<"j "<<t[j]<<endl; if(t[j]<=cur) { cur=t[j]; }else{ break; } } } i=j-1;cur=1;//回到一楼 } } } ans+=cur-1;//最后拿完之后也要回到一楼 cout <<ans; }
问题 D: 吃席
时间限制: 1 Sec 内存限制: 128 MB题意:
有一圆桌,上面有n个菜按照顺序排成一圈,而飞飞只能够到身边的m道菜,对于每道菜都有它的美味值vi,请你帮飞飞找到一个好位置,让飞飞吃到的菜的美味值之和最大。
解析:
当然你可以直接暴力,对于每m个相邻的菜的美味值求和,然后找最大值,但是看数据范围这样显然超时。
想到每次找相邻m个菜的时候,只不过去掉了最前面一道菜且增加了一道菜,可以想到,其实用一遍循环就可以了,只需要记录一下最前面那道菜的位置,然后每次求和完的时候,去掉最前面那道菜的美味值。
注:这里将最前面的菜放到最后面菜的后面,相当于圆桌,当然你也可以取模实现。
主要代码:
int v[N]; void solve() { int n,m,ans=0; cin >>n>>m; for(int i=1;i<=n;i++) { cin >>v[i]; v[i+n]=v[i]; } int l=1,r=1,res=0; while(r<n+m) { while(r-l+1<=m) { res+=v[r++]; } //cout <<res<<endl; ans=max(ans,res); res-=v[l++];//以下一个为起点 } cout <<ans<<endl; }
问题 E: 嘉嘉的序列游戏
时间限制: 1 Sec 内存限制: 128 MB题意:
给你一个包含N个数字的序列S,形式如(S1,S2,S3,...,Sn)。请你找到有多少个包含
N个整数的序列A,能够同时满足以下两个条件。其中:序列A的形式如(A1,A2, A3,...,An)。
●1≤Ai≤Si;(1≤i≤N)
●Ai≠Aj; (1≤i<j≤N)
因为序列计数的结果可能会很大,请你输出取模(10^9 + 7)之后的结果。解析:
以最小的数作为突破口,由排列组合的知识可知,当最小的数取1的时候,第二小的数则不能取1,第三小的数则不能取1,2。将他们可以取到的个数分别相乘得出结果。
依次类推,设Si是第i(从0开始)小的数,那么他可以取1至Si,对于取的每一个数来说,其他位置可取到的数的个数为(Si-i)个,故总的序列个数为S1*(S2-1)*...*(Sn-n-1),最后记得取模。
主要代码:
#include<bits/stdc++.h> #define int long long #define PII pair<int,int> #define fi first #define se second #define pb push_back #define N 200005 const int mod=1e9+7; const int inf=0x3f3f3f3f; using namespace std; int gcd(int a,int b){return b?gcd(b,a%b):a;} void solve() { int n; cin >>n; vector<int>v(n); for(int i=0;i<n;i++) { cin >>v[i]; } sort(v.begin(),v.end()); int ans=1; for(int i=0;i<n;i++) { if(v[i]<=0) { ans=0;break; }else{ ans=ans*(v[i]-i)%mod; } } cout <<ans<<endl; } signed main() { ios::sync_with_stdio(0);cin.tie(0);cout.tie(0); int t = 1; cin >> t; while(t--) { solve(); } return 0; }
问题 F: 情书
时间限制: 1 Sec 内存限制: 128 MB题意:
阿珍写了一封情书,不过情书进行了以下加密:
首先,阿珍的情书虽然号称情书,但其实只有一句,包含了合法可显示的字符,其中首位为大写字母。
第一步,先将情书里所有的字符都根据其ASCII码转换为7位二进制数,连在一起组成一个字符串x。
第二步,将x的最后一位放到第一位,其他位置依次后移,得到新的字符串y。再将x和y按位异或,得到字符串z。
第三步,将z的每7位还原成一个十进制数,如果该数在大小写字母范围内,则替换为相应的字母,否则保存为三位十进制数。
现在给出加密后的字符串,求情书内容。
解析:
直接倒推即可,第一步求出z,然后根据z的首字符判断x,y的首字符,如果为0,则有两种可能,x,y的首字符同样为0或者1。那么再根据z的值可以一直求出x,y即:
根据x,y的关系可知,设xy的长度为3,有x为x0,x1,x2,y为x2,x0,x1;根据z0,z1,可求出x,y。
然后得到x有两个值,但只取首位为1的值!(其中首位为大写字母ASCCI>=65)。最后转化成字符输出即可。
主要代码:
#include<bits/stdc++.h> #define int long long #define PII pair<int,int> #define fi first #define se second #define pb push_back #define N 200005 const int mod=1e9+7; const int inf=0x3f3f3f3f; using namespace std; int gcd(int a,int b){return b?gcd(b,a%b):a;} void check(char cur_x,char cur_y,string z,string &ans) { string x="",y=""; x=x+cur_x,y=y+cur_y+cur_x;// //'1'^'0'='1' (49^48==1) for(int i=1;i<z.size()-1;i++) { int k=z[i]^y[i]; x=x+to_string(k); y=y+to_string(k); } ans=x+cur_y; } void solve() { string s; while(cin >>s) { string x,z,ans; for(int i=0;i<s.size();i++) { int res=0; if(s[i]>='0'&&s[i]<='9') { int j=i; while(j-i<3&&s[j]>='0'&&s[j]<='9') { res=res*10+s[j++]-'0'; } i=j-1; }else{ res=(int)s[i]; } for(int k=6;k>=0;k--) { z=z+to_string(res>>k&1); } } //cout <<z<<endl; if(z.front()=='0') { check('1','1',z,x); }else{ check('1','0',z,x); } //cout <<x<<endl; for(int i=0;i<x.size();i+=7) { string st=x.substr(i,7); //cout <<st<<endl; int res=0; for(int j=0;j<7;j++) { if(st[j]=='1') res+=1<<(7-j-1); } ans=ans+(char)res; //cout <<res<<endl; } cout <<ans<<endl; } } signed main() { ios::sync_with_stdio(0);cin.tie(0);cout.tie(0); int t = 1; //cin >> t; while(t--) { solve(); } return 0; }
问题 G: 云顶之奕
时间限制: 1 Sec 内存限制: 128 MB题意:
有一个4*7的符文矩阵,1代表强化符文,2代表普通符文,0代表没有符文,强化符文可以让相邻的符文增强25的能力值,符文初始值为100。
解析:
根据题意,将偶数行的符文右移一个单位,这样使得,一个强化符文可以强化上,下,左,右,左下,左上的符文,用循环模拟即可。那么对于奇数行来说,一个强化符文可以强化上,下,左,右,右下,右上的符文。
主要代码:
#include <bits/stdc++.h> #define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); #define int long long #define endl '\n' #define N 200005 #define fi first #define se second #define pb push_back using namespace std; const int inf=0x3f3f3f3f; const double ex=acos(-1); const int mod=1e9+7; int gcd(int a,int b){return b? gcd(b,a%b) : a ;} typedef pair<int,int>PII; priority_queue<int,vector<int>,greater<int> > q;//越来越大 int a[10][10],v[10][10]; int dx1[]={0,0,1,1,-1,-1},dy1[]={-1,1,0,-1,0,-1}; int dx2[]={0,0,1,1,-1,-1},dy2[]={-1,1,0,1,0,1}; void solve() { for(int i=1;i<=4;i++) { if(i&1) { for(int j=1; j<=7; j++) { cin >>a[i][j]; if(a[i][j]!=0) v[i][j]=100; else v[i][j]=0; } } else { for(int j=2; j<=8; j++) { cin >>a[i][j]; if(a[i][j]!=0) v[i][j]=100; else v[i][j]=0; } } } for(int i=1;i<=4;i++) { if(i&1) { for(int j=1; j<=7; j++) { if(a[i][j]==1) { for(int k=0; k<6; k++) { int x=i+dx2[k],y=j+dy2[k]; if(a[x][y]!=0) v[x][y]+=25; } } } } else { for(int j=2; j<=8; j++) { if(a[i][j]==1) { for(int k=0; k<6; k++) { int x=i+dx1[k],y=j+dy1[k]; if(a[x][y]!=0) v[x][y]+=25; } } } } } for(int i=1;i<=4;i++) { if(i&1) { for(int j=1; j<=7; j++) { cout <<v[i][j]<<" "; } } else { for(int j=2; j<=8; j++) { cout <<v[i][j]<<" "; } } if(i!=4) cout <<endl; } } signed main() { ios int t = 1; cin >>t; while(t--) { solve(); //cout <<t; if(t!=0) { cout <<endl; } } }
问题 H: 夏季大三角
时间限制: 1 Sec 内存限制: 128 MB题意:
还没看懂题目...
解析:
主要代码:
问题 I: 无限梦境的概率理论
时间限制: 1 Sec 内存限制: 128 MB题意:
抽一次出SSR角色的概率是p1。如果抽了n次还没有出SSR角色,则接下来每次抽卡时概率将会提升p2 (提升可以累积),直到抽出SSR (概率大于等于1视为一定抽出SSR), 抽出SSR后出SSR角色的概率重回p1。
求这个游戏抽卡每出一个SSR角色的期望抽卡次数ans。解析:
由期望的定义可知,ans是所有抽中SSR所需要次数的可能值分别乘以对应的概率的和,那么一直模拟直到概率大于1为止。
主要代码:
void solve() { double p1,n,p2; cin >>p1>>n>>p2; double ans=0,v=1; int i; for(i=1;p1<1;i++) { ans+=v*i*p1; v=v*(1-p1); if(i>=n) p1+=p2; } ans+=v*i; printf("%.6lf",ans); }