问题 A: 新的希望
时间限制: 1 Sec 内存限制: 128 MB题意:
输入仅一个大于2021的整数。输出“A New Hope”;
解析:
直接输出“A New Hope”即可。
主要代码:
void solve() { int n; cin >>n; cout <<"A New Hope"; }
问题 B: 嘉嘉的队伍配置
时间限制: 1 Sec 内存限制: 128 MB
题意:
现有了n位输出角色和m位辅助角色,而且每位角色最多只能加入一个队伍。现在他想配置尽可能多的“强力的队伍”,求最多能配置多少支“强力的队伍”?
一支“强力的队伍”,必须要同时满足以下三个条件:
1、队伍中的角色人数为4,即达到队伍的最大人数
2、队伍中至少要拥有一位输出角色
3、队伍中至少要拥有一位辅助角色解析:
贪心思维,首先将一位输出和一位辅助放在一队,看能组成多少队,显然取决取两者间位数小的那个角色,然后就是补全,看看分完之后多出来几位角色,将他们补至前面空缺能凑成多少强力的队伍,然后在剩下的队伍之间互相补全(也可能前面已经补完空缺),两者凑出来的“强力的队伍”之和即为结果。
主要代码:
void solve() { int n,m,ans=0; cin >>n>>m; int k=max(n,m)-min(n,m); int res=min(n,m); if(k/2>=res) { cout <<res<<endl; }else{ cout <<k/2+(res-k/2)/2<<endl; } }
问题 C: 寻找厄咒图腾
时间限制: 1 Sec 内存限制: 128 MB
题意:
使用"hex"表示图腾,可以随意删除字符串中的字母,然后,每当在删除后的字符串中完整地组合出一个"hex"这个词,我们就认为找到一个图腾。例如:长度为5的字符串"heexh",删除两个字符后变成"hex",有一个图腾。长度为9的字符串"ehehexhex",删去前三个字符后变成"hexhex",有两个图腾。求最后可以从照片中找到的最多的图腾的数量。
解析:
hex是有顺序的,exh不是一个图腾,那么我们可以从找到一个h开始计数,找到h再找e,找到e再找x,直到找到x后重新开始找h。
主要代码:
void solve() { int n,ans=0,h=0,e=0; string s; cin >>n>>s; for(int i=0;i<n;i++) { if(s[i]=='h') h++; if(h!=0&&s[i]=='e') e++; if(h!=0&&e!=0&&s[i]=='x') { e=0;h=0;ans++; } } cout <<ans<<endl; }
问题 D: 嘉嘉的棋盘游戏
时间限制: 1 Sec 内存限制: 128 MB
题意:
有国王和刺客阵营,我们为刺客,国王在n*m的棋盘上,我们可以放置多个刺客,每放一次当前刺客距离国王的位置是已知的,求最少放置多少个刺客可以知道国王的位置。
解析:
如果放在棋盘中间,那么第一次已知距离,国王最多有八种可能,可以发现刺客放在棋盘的角落时,国王最多有四种可能,而且环绕角落周围,且看成一个四分之一圆,那么两个四分之一圆的交点可以唯一确定国王的位置,可以发现最少两个刺客即可确定位置,当然还有特殊情况,棋盘只有一个点时,无需放置刺客,只有一行或者一列时,只需要放置一次。
主要代码:
void solve() { int n,m,ans=0; cin >>n>>m; if(n==1&&m==1) { cout <<0<<endl;return ; } if(n==1||m==1) { cout <<1<<endl; }else{ cout <<2<<endl; } }
问题 E: 爱丽丝的人偶
时间限制: 1 Sec 内存限制: 128 MB题意:
有n个人编号从0-n-1,依次循环报数,报到奇数的出列,求第q个离开队伍的人的编号是多少。
解析:
为方便计算,设编号为1-n,最后答案-1即可。可以发现第一次循环报数出列的为1,3,5,7...(2*i-1)。(i表示当前循环第i位出列的人),第二次:2,6,10,14...(4*i-2),第三次:4,12,20,28...(8*i-4),第四次:...(16*i-8)。可以发现有数学规律,那么我们需要找到在第几层循环出列的人数已经超过q,由数学关系可求得q在当前循环中是第几位出列的,然后由推导公式得到编号,最后减一得到答案。
主要代码:
void solve() { int n,q; cin >>n>>q; int k=n,res=2,cnt=0; while(k) { int sum=k/2; if(k&1) sum++; cnt+=sum; if(cnt>=q) { cout <<res*(sum-cnt+q)-res/2-1<<endl;return ; } //cout <<cnt<<" "<<res<<endl; k/=2;res*=2; } }
问题 F: 遥望远方,答案就在天空的那一端!
时间限制: 1 Sec 内存限制: 128 MB题意:
已知当前位置,有n个重力粒子,每踩一次就会跳到与该重力粒子对称的位置,求能跳到最高的高度。
解析:
看到最高,首先贪心思维,每次踩最低或者最高的粒子,这样可以使向上跳的时候最高,那么就可能有两种策略,下上下上下上...,上下上下上下...,也就是根据粒子个数确定采取何种策略,保证最后一步是上即可,而每次的取法是取最上面那个粒子或者最下面那个粒子,这样可以使得最后高度最高。
主要代码:
void solve() { int n,ans; cin >>n>>ans; for(int i=1;i<=n;i++) { cin >>a[i]; } int l=1,r=n; if(n&1) { for(int i=1;i<=n;i++) { if(i&1) { ans=2*a[r--]-ans; }else{ ans=2*a[l++]-ans; } } }else{ for(int i=1;i<=n;i++) { if(i&1) { ans=2*a[l++]-ans; }else{ ans=2*a[r--]-ans; } } } cout <<ans<<endl; }
问题 G: [Ynoi2048] 这里没有数据结构
时间限制: 1 Sec 内存限制: 128 MB题意:
一个倒圆锥上不封顶,一个球,求将球和液体放进圆锥中液体不接触到球的最大体积。
解析:
数学题,球和圆锥有两种情况,圆锥两边延长线和球相切和相交,那么分两种情况作图,可分别求出两种情况最大体积,那么重点在于如何判断相切或者相交,取极值即可,求恰好与圆锥两边边界相切的球的半径为多少,以此为分界线,判断是否相切。
主要代码:
void solve() { int r,h,R; cin >>r>>h>>R; if(R<=sqrt(r*r+h*h)*r/h) { printf("%.2f",acos(-1)*r*r*pow(R*sqrt(r*r+h*h)/r-R,3)/(3*h*h)); }else{ printf("%.2f",acos(-1)*r*r*pow(sqrt(R*R-r*r)+h-R,3)/(3*h*h)); } }
问题 H: 烟花易逝
时间限制: 1 Sec 内存限制: 128 MB题意:
这张照片里以某一点(a,b)为中心的烟花最大可能的半径是多少?
半径为R的烟花定义是:所有与中心点的距离小于等于R的点都必须在照片内,对于这些点,将其与在照片内的所有的相邻点比较,离中心点较近的点亮度较大。即当两个在照片中的点(xi,yi),(xj,yj)满足|xi-a|+|yi-b|<=R&&|xj-a|+|yj-b|<=R时,如果|xi-a|+|yi-b|<|xj-a|+|yj-b|且|xi-xj|+|yi-yj|==1,则light(xi,yi)>light(xj,yj)。解析:
想到bfs,可以从0-50枚举半径,因为半径不可能超过50,为加快枚举速度可以采取二分查找最大半径,然后对于每一个半径,用bfs判断是否可行,对于每一步,向距离中心点大的前进,而且要满足半径小于当前R,问题在于每一个点需要与距离远的比较大小,如果小于等于则不合题意,而且每一个点只需前进一次即可。
主要代码:
#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 1005 #define fi first #define se second #define pb push_back using namespace std; typedef unsigned long long ULL; // 0 ~ 2^64 - 1, 溢出相当于取模 const int inf=0x3f3f3f3f; const int P=131; // P 取 131 或 13331 为经验值 const double ex=1e-7; const int mod=998244353; 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 n,a[N][N],v[N][N],x,y; int dx[]={0,0,1,-1},dy[]={1,-1,0,0}; int bfs(int R) { queue<PII>q; q.push({x,y}); while(q.size()) { PII t=q.front(); q.pop(); for(int i=0;i<4;i++) { int l=t.fi+dx[i],r=t.se+dy[i]; //cout <<l<<" "<<r<<endl; if(abs(l-x)+abs(r-y)<=R&&abs(l-x)+abs(r-y)>abs(t.fi-x)+abs(t.se-y)) { if(l<=n&&l>=1&&r<=n&&r>=1) { if(a[l][r]>=a[t.fi][t.se]) { //cout <<l<<" "<<r<<endl; return 0; }else{ //cout <<l<<" "<<r<<endl; if(!v[l][r]) q.push({l,r}); v[l][r]=1; } }else{ //cout <<l<<" "<<r<<endl; return 0; } } } } return 1; } void solve() { int l=1,r=50; while(l<r) { for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) v[i][j]=0; int mid=(l+r)/2; if(!bfs(mid)) r=mid; else l=mid+1; } cout <<r-1<<endl; } int main() {//ios int q; cin >>n>>q; for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { cin >>a[i][j]; } } while(q--) { cin >>x>>y; solve(); } return 0; }
问题 I: 亲和数
时间限制: 1 Sec 内存限制: 128 MB题意:
两个正整数中,彼此的全部约数之和(本身除外)与另一方相等,则称这两数为亲和数。例如,220和284就互为亲和数。
求1-n中亲和数的个数。
解析:
关键在于求每个数的真因子和,直接约数枚举显然超时O(n*logn),可以联想到素数筛,一个数的真因子一定小于等于它的一半,故还可以优化。用类素数筛的方法实现O(n*log(logn))的时间复杂度,从而避免超时。
注:如果一个数的真因子的和的真因子的和为它本身,那么他们互为亲和数。
埃氏筛:
void getPrime(int n) { for(int i=2;i<=n;++i) isPrime[i] = true; //假设2-n都是素数 for(int i=2;i<=n;++i) //遍历2-n里面所有数 if(isPrime[i]) //如果i是素数 //i是素数的话,那么i的倍数肯定就不是合适 //即 i*2,i*3 .....i*j肯定不是素数,注意边界i*j<=n for(int j=i;i*j<=n;++j) //n以内,且是i的倍数的数肯定不是素数,设为false isPrime[i*j] = false; }
本题代码:
#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 1000005 #define fi first #define se second #define pb push_back using namespace std; typedef unsigned long long ULL; // 0 ~ 2^64 - 1, 溢出相当于取模 const int inf=0x3f3f3f3f; const int P=131; // P 取 131 或 13331 为经验值 const double ex=1e-7; const int mod=998244353; 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 n,f[N],m[N]; signed main() {ios for(int i=1;i+i<=N;i++) { for(int j=2*i;j<=N;j+=i) { m[j]+=i; } } for(int i=1;i<=N;i++) { f[i]=f[i-1]; if(i>m[i]&&m[m[i]]==i) { f[i]=f[i-1]+1; //cout <<m[i]<<" "<<i<<endl; } } while(cin >>n) { cout <<f[n]<<endl; } return 0; }