比赛传送门
求字符串中最后一次出现 a a a 的位置,若没有输出 − 1 -1 −1 。
不讲。
#include
using namespace std;
string s;
int ans=-1;
int main(){
cin>>s;
for(int i=0;i<s.size();++i) if(s[i]=='a') ans=i+1;
cout<<ans<<endl;
return 0;
}
给定无向图,求每个与每个点相邻的点有多少,并从小到大输出点的编号。
邻接表 + + + 排序,不讲。
#include
using namespace std;
int n,m,a[100010];
vector<int>w[100010];
int main(){
cin>>n>>m;
for(int i=1;i<=m;++i){
int u,v;
cin>>u>>v;
w[u].push_back(v);
w[v].push_back(u);
}
for(int i=1;i<=n;++i){
int siz=w[i].size();
cout<<siz<<' ';
for(int j=1;j<=siz;++j) a[j]=w[i][j-1];
sort(a+1,a+siz+1);
for(int j=1;j<=siz;++j) cout<<a[j]<<' ';
cout<<endl;
}
return 0;
}
给定 1 1 1 , , , 2 2 2 . . . ... ... n n n 的某种排列,求按字典序大小的上一个排列。
题目就是答案, S T L STL STL 自带函数 p r e v prev prev_ p e r m u t a t i o n permutation permutation ,解决。
#include
using namespace std;
int n,a[110];
int main(){
cin>>n;
for(int i=1;i<=n;++i) cin>>a[i];
prev_permutation(a+1,a+n+1);
for(int i=1;i<=n;++i) cout<<a[i]<<' ';
cout<<endl;
return 0;
}
给定一个数组,将每个数除以 2 2 2 或 3 3 3 任意多次,使得最后所有数都相同。求最小操作数。
显然,要使操作数最少,最后剩下的数也要是所有情况中最大的(否则,可以少除一次 2 2 2 或 3 3 3 )。于是,可以先求出所有数的最大公约数,然后将最大公约数一直除以 2 2 2 和 3 3 3 ,最后根据剩下的数求操作次数。算法复杂度 O ( n log n ) O(n\log n) O(nlogn) 。
#include
using namespace std;
int n,a[1010],ag,ans=0;
int gcd(int u,int v){
return v?gcd(v,u%v):u;
}
int main(){
cin>>n;
for(int i=1;i<=n;++i){
cin>>a[i];
if(i==1) ag=a[i];
else ag=gcd(ag,a[i]);
}
for(int i=1;i<=n;++i){
int gd=a[i]/ag;
while(!(gd%2)) gd/=2,ans++;
while(!(gd%3)) gd/=3,ans++;
if(gd!=1){
cout<<-1<<endl;
return 0;
}
}
cout<<ans<<endl;
return 0;
}
有一个迷宫,从某一点出发,不重复经过任何点走一条长度大于等于 4 4 4 的路径并回到原点,问是否存在这样的路径。
一,骗分,期望得分 50 50 50 。
二,正经的分析。
首先,如果存在这样的路径,其长度一定大于等于 4 4 4 (显而易见的)。
那么,我们只需要考虑,是否能找到一条从起点出发的路径,使得这条路径构成了一个环。
其实,如果把起点挖掉,此题相当于从起点旁边的四个点(也可能 ≤ 3 \le 3 ≤3 个)出发,能否到达起点。但是要排除一步到位的情况,即直接回到起点。为了解决这个问题,我们不妨将这四个点再扩散一次,即从起点旁边的点的旁边的点(视为起点)出发,不经过扩散到它的起点旁边的点而到达起点(视为终点),这样就是一条合法路径。
#include
using namespace std;
int dx[4]={1,0,-1,0},dy[4]={0,1,0,-1};
struct nod{
int x,y;
};
queue<nod>q;
int n,m,sx,sy;
string cins;
bool check(int idx,int idy){//检查超出边界用的,方便一点
if(idx<1||idy<1||idx>n||idy>m) return 0;
return 1;
}
int main(){
cin>>n>>m;
char c[n+10][m+10];
bool vh[n+10][m+10];
for(int i=1;i<=n;++i){
cin>>cins;
for(int j=1;j<=m;++j){
c[i][j]=cins[j-1];
if(c[i][j]=='S') sx=i,sy=j;
}
}
for(int i=0;i<4;++i){
int nx=sx+dx[i],ny=sy+dy[i];//一次扩散
if(!check(nx,ny)||c[nx][ny]=='#') continue;
for(int j=0;j<4;++j){
int inx=nx+dx[j],iny=ny+dy[j];//二次扩散
if(!check(inx,iny)||c[inx][iny]=='#') continue;
if(inx!=sx||iny!=sy){//合法的起点
memset(vh,0,sizeof(vh));
vh[nx][ny]=1;
q.push(nod{inx,iny});
while(!q.empty()){//宽搜以判断能否到达
nod now=q.front();
q.pop();
if(now.x==sx&&now.y==sy){
cout<<"Yes"<<endl;
return 0;
}
if(vh[now.x][now.y]) continue;
vh[now.x][now.y]=1;
//cout<
for(int l=0;l<4;++l){
int ntx=now.x+dx[l],nty=now.y+dy[l];
if(!check(ntx,nty)||c[ntx][nty]=='#') continue;
q.push(nod{ntx,nty});
}
}
}
}
}
cout<<"No"<<endl;
return 0;
}
算法复杂度 O ( H × W ) O(H\times W) O(H×W) 。
F F F 题期望,不会。
G G G 题打的是 O ( n m 2 ) O(nm^2) O(nm2) 算法,后来想出 O ( n m ) O(nm) O(nm) 算法,没打,但还是超时。
E x Ex Ex 不用看,不会。
用时 44 : 30 + 5 m i n 44:30+5min 44:30+5min , 1500 1500 1500 分, 986 986 986 名。
总结:
S T L STL STL 是个好东西。
代码实现能力有待提高。
S T L STL STL 自带数据结构要熟练运用。