PAT甲级(1001-1015)

题目列表知识点
1001 A+B Format (20 分)模拟(字符串)
1002 A+B for Polynomials (25 分)多项式加法模拟(数组)
1003 Emergency (25 分)Dij最短路(最短路条数)
1004 Counting Leaves (30 分)BFS/DFS(逐层遍历树)
1005 Spell It Right (20 分)字符串简单题
1006 Sign In and Sign Out (25 分)结构体排序/求最大、最小值
1007 Maximum Subsequence Sum (25 分)在线处理
- 1008 Elevator (20 分)简单模拟
1009 Product of Polynomials (25 分)多项式乘法模拟(数组)
1010 Radix (25 分)进制转换,二分
1011 World Cup Betting (20 分)简单题
1012 The Best Rank (25 分)结构体排序
1013 Battle Over Cities (25 分)DFS求连通块个数
1014 Waiting in Line (30 分)队列模拟
1015 Reversible Primes (20 分)进制转化,质数判断

1001 A+B Format (20 分)

计算a+b,输出结果时,如果a+b位数大于3位,则每输出三位加一个逗号。

注意结果为负的情况。

直接转为字符串,字符串输出时进行相应处理既可。

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn=100005;
int main()
{
    ll a,b,c;
	cin>>a>>b;
	c=a+b;
    if(c<0){//结果为负,则先输出负号
        c=abs(c);//取绝对值
        cout<<"-";
    }
    string s=to_string(c);//转化为字符串
    if(s.length()<=3)//结果小于等于3位,直接输出
        cout<<s;
    else{//结果大于3位,每三位输出一个逗号
        //从低位开始,每隔三位,加一个逗号,
        //注意以下情况:
        //123,456,789
        //12,345,678
        int cnt=s.length();//相当于把每个元素的序号颠倒了过来,第一个元素的序号是s.length()-1
        for(int i=0;i<s.length();i++){
            if(cnt%3==0&&cnt!=s.length()&&i!=s.length()-1){//第一位和最后一位,均不加逗号
                cout<<",";
            }
            cout<<s[i];
            cnt--;
        }
    }
	return 0;
}

1002 A+B for Polynomials (25 分)

模拟多项式加法

指数相同项,系数相加

注意系数为0的情况!!!

/*其实根本不需要开三个数组,以前写的代码还是太过稚嫩了,输入的同时就可以进行多项式加法了,对应系数相加即可*/
#include<iostream>
using namespace std;
const int maxn=10005;
double d[maxn];//下标为指数,值为系数
int main(){
    int n,m;
    double coef;//系数
    int exp;//指数
    cin>>n;
    int mmax=0;//指数最大值
    while(n--){
        cin>>exp>>coef;
        d[exp]+=coef;//将系数和指数对应
        mmax=max(mmax,exp);
    }
    cin>>m;
    while(m--){
        cin>>exp>>coef; 
        d[exp]+=coef;
        mmax=max(mmax,exp);
    }
    int num=0;//项数
    for(int i=mmax;i>=0;i--){
           if(d[i]) num++;
    }
    printf("%d",num);
    for(int i=mmax;i>=0;i--){
        if(d[i]){
            printf(" %d %.1lf",i,d[i]);
        }
    }
    printf("\n");
    return 0;
}

1003 Emergency (25 分)

题目大意:

给定一张国家地图,地图上显示了这个国家中连接不同城市的所有道路,并标明了道路的长度;每个城市所拥有的救援队数量也标明在地图上。当你接到来自其他城市的紧急呼救任务时,你需要在最快到达目的地的同时在沿途城市召集尽可能多的救援队。

求:最短路的数量和能召集的救援队数量的最大值

最短路问题,路径长度最短的同时,该路径上救援队总数量要最多。

dij求最短路的同时,维护最短路数量和救援队数量

1、数据很小:邻接矩阵存图(无向图,存边时,注意数组大小要开两倍)

2、dij单源最短路模板

3、在更新最短路的同时,维护最短路的数量和救援队数量

4、出现两条路长度相等时,最短路数量加1,更新救援队数量为较大值

邻接矩阵写法

#include<bits/stdc++.h>
#define pb push_back
#define mpi make_pair
#define fi first
#define se second
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define pi acos(-1)
using namespace std;
const int maxn=1e3+10;
const int mod=1e9+7;
const int INF=0x3f3f3f3f;
typedef long long ll;
inline ll lowbit(ll x){return x&(-x);}
int n,m,s,t;
int e[maxn][maxn];//存图
int vis[maxn];//标记节点是否被访问过
int dis[maxn];//从起点到某点的最短距离
int cure[maxn];//某城市的救援队数量
int c[maxn];//从起点到某点能召集的救援队数量
int num[maxn];//最短路的条数
void dij(){
    memset(dis,0x3f,sizeof(dis));
    for(int i=0;i<n;i++){
    	dis[i]=e[s][i];//从s直接到i的距离
    }
    c[s]=cure[s];//起点最短路数量就是cure[s]
    num[s]=1;//最短路数量初始为1条
    for(int i=0;i<n;i++){
        int mmin=INF,u=-1;
        for(int j=0;j<n;j++){//寻找距离起点最近的点u
            if(!vis[j]&&dis[j]<mmin){
                mmin=dis[j];
                u=j;
            }
        }
        if(u==-1) break;//若无法再找到这样的点,说明最短路已经更新完毕,无需再找
        vis[u]=1;//标记该点已被访问过
        for(int j=0;j<n;j++){
            if(!vis[j]&&dis[j]>dis[u]+e[u][j]){//更新最短路
                dis[j]=dis[u]+e[u][j];
                c[j]=c[u]+cure[j];//更新救援队数量
                num[j]=num[u];//最短路数量并未增加
            }
            else if(!vis[j]&&dis[j]==dis[u]+e[u][j]){
                num[j]+=num[u];//最短路条数加1
                if(c[u]+cure[j]>c[j]){//维护救援队数量
                    c[j]=c[u]+cure[j];
                }
            }
        }
    }
    cout<<num[t]<<" "<<c[t]<<endl;
}
int main(){
    cin>>n>>m>>s>>t;
    for(int i=0;i<n;i++){
        for(int j=0;j<n;j++){
            if(i==j) e[i][j]=0;
            else e[i][j]=INF;
        }
    }
    for(int i=0;i<n;i++){
        cin>>cure[i];
    }
    for(int i=0;i<m;i++){
        int u,v,w;
        cin>>u>>v>>w;
        e[u][v]=e[v][u]=w;
    }
    dij();
    return 0;
}

链式前向星(边集数组写法)

#include<bits/stdc++.h>
#define pb push_back
#define mpi make_pair
#define fi first
#define se second
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define pi acos(-1)
using namespace std;
const int maxn=1e5+10;
const int mod=1e9+7;
const int INF=0x3f3f3f3f;
typedef long long ll;
inline ll lowbit(ll x){return x&(-x);}
int head[maxn];
int n,m,s,t,cnt;
struct edge{
	int u,v,w;
	int next;
}e[maxn];//存边,数组开大一点
void add(int u,int v,int w){
	e[cnt].u=u;
	e[cnt].v=v;
	e[cnt].w=w;
	e[cnt].next=head[u];
	head[u]=cnt++;
}   
int dis[maxn];
int vis[maxn];
int c[maxn];
int num[maxn];
int cure[maxn];
void dij(){
	memset(dis,INF,sizeof(dis));
	dis[s]=0;
	c[s]=cure[s];
	num[s]=1;
	for(int i=0;i<n;i++){
		int mmin=INF,u=-1;
		for(int j=0;j<n;j++){
			if(!vis[j]&&dis[j]<mmin){
				mmin=dis[j];
				u=j;
			}
		} 
		if(u==-1) break;
		vis[u]=1;
		for(int j=head[u];j!=-1;j=e[j].next){
			int v=e[j].v;
			if(dis[v]>dis[u]+e[j].w){
				dis[v]=dis[u]+e[j].w;
				num[v]=num[u];
				c[v]=c[u]+cure[v];
			}
			else if(dis[v]==dis[u]+e[j].w){
				num[v]+=num[u];
				c[v]=max(c[v],c[u]+cure[v]);
			}
		}
	}
	cout<<num[t]<<" "<<c[t]<<endl;
	
}                                            
int main(){
	cin>>n>>m>>s>>t;
	memset(head,-1,sizeof(head));
	for(int i=0;i<n;i++){
		cin>>cure[i];
	}
	for(int i=0;i<m;i++){
		int u,v,w;
		cin>>u>>v>>w;
		add(u,v,w);
		add(v,u,w);
	}
	dij();
	return 0;
	
}

优先队列优化dij

#include<bits/stdc++.h>
#define pb push_back
#define mpi make_pair
#define fi first
#define se second
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define pi acos(-1)
using namespace std;
const int maxn=1e5+10;
const int mod=1e9+7;
const int INF=0x3f3f3f3f;
typedef long long ll;
typedef pair<int,int> p;
inline ll lowbit(ll x){return x&(-x);}
int head[maxn];
int n,m,s,t,cnt;
struct edge{
	int u,v,w;
	int next;
}e[maxn];//存边,数组开大一点
void add(int u,int v,int w){
	e[cnt].u=u;
	e[cnt].v=v;
	e[cnt].w=w;
	e[cnt].next=head[u];
	head[u]=cnt++;
}   
int dis[maxn];
int vis[maxn];
int c[maxn];
int num[maxn];
int cure[maxn];
void dij(){
	priority_queue<p,vector<p>,greater<p> >q;
	memset(dis,INF,sizeof(dis));
	dis[s]=0;
	c[s]=cure[s];
	num[s]=1;
	q.push(p(0,s));//最短距离,顶点编号
	while(!q.empty()){
		int u=q.top().second;
		q.pop();
		if(vis[u]) continue;
		vis[u]=1;
		for(int i=head[u];i!=-1;i=e[i].next){
			if(dis[e[i].v]>dis[u]+e[i].w){
				dis[e[i].v]=dis[u]+e[i].w;
				num[e[i].v]=num[u];
				c[e[i].v]=cure[e[i].v]+c[u];
				q.push(p(dis[e[i].v],e[i].v));//更新优先队列
			}
			else if(dis[e[i].v]==dis[u]+e[i].w){
				num[e[i].v]+=num[u];
				c[e[i].v]=max(c[e[i].v],c[u]+cure[e[i].v]);
			}
		}
	}
	cout<<num[t]<<" "<<c[t]<<endl;
	
}                                            
int main(){
	cin>>n>>m>>s>>t;
	memset(head,-1,sizeof(head));
	for(int i=0;i<n;i++){
		cin>>cure[i];
	}
	for(int i=0;i<m;i++){
		int u,v,w;
		cin>>u>>v>>w;
		add(u,v,w);
		add(v,u,w);
	}
	dij();
	return 0;
	
}

1004 Counting Leaves (30 分)

题目大意:

统计每一层的叶子节点的数量

用vector将节点的所有儿子节点都记录下来

1、从根节点开始,BFS逐层搜索,没有儿子的节点则为叶子节点。

#include<bits/stdc++.h>
#define pb push_back
#define mpi make_pair
#define fi first
#define se second
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define pi acos(-1)
using namespace std;
const int maxn=1e3+10;
const int mod=1e9+7;
const int INF=0x3f3f3f3f;
typedef long long ll;
inline ll lowbit(ll x){return x&(-x);}
vector<int>v[maxn],ans;
int n,m;
void bfs(){
    queue<int>q;
    q.push(1);
    while(!q.empty()){
        int k=q.size();
        int cnt=0;
        for(int i=0;i<k;i++){//逐层遍历,当前队列中的所有元素即为同一层的所有节点
            int s=q.front();
            q.pop();
            if(v[s].size()==0) cnt++;
            else{
                for(int j=0;j<v[s].size();j++){
                    q.push(v[s][j]);
                }
            }
        }
        ans.pb(cnt);
    }
    cout<<ans[0];
    for(int j=1;j<ans.size();j++){
        cout<<" "<<ans[j];
    }
    cout<<endl;
}
int main(){
    cin>>n>>m;
    for(int i=0;i<m;i++){
        int id,k;
        cin>>id>>k;
        while(k--){
            int x;
            cin>>x;
            v[id].pb(x);
        }
    }
    bfs();
    return 0;

}

2、dfs搜索,从根节点开始,一旦遇到叶子节点时,对应层数的叶子节点个数加1

#include<bits/stdc++.h>
#define pb push_back
#define mpi make_pair
#define fi first
#define se second
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define pi acos(-1)
using namespace std;
const int maxn=1e3+10;
const int mod=1e9+7;
const int INF=0x3f3f3f3f;
typedef long long ll;
inline ll lowbit(ll x){return x&(-x);}   
int n,m,h;    
vector<int>v[maxn];     
map<int,int>mp;
void dfs(int root,int level){
	if(v[root].size()==0){
		mp[level]++;//更新当前层的叶子节点个数
		h=max(h,level);
		return;
	}
	for(int i=0;i<v[root].size();i++){
		dfs(v[root][i],level+1);
	}
}               
int main(){
	cin>>n>>m;
	while(m--){
		int id,k;
		cin>>id>>k;
		while(k--){
			int x;
			cin>>x;
			v[id].pb(x);
		}
	}
	dfs(1,0);
	cout<<mp[0];
	for(int i=1;i<=h;i++){
		cout<<" "<<mp[i];
	}
	cout<<endl;
	return 0;
	
}

1005 Spell It Right (20 分)

题目大意:

求出一个非负整数各位数字相加之和,并用英文输出结果。

例如:15,输出:one five

简单题,由于N的范围太大,故用字符串存储,逐位相加求和。最后按照题目要求输出最终结果。

#include<bits/stdc++.h>
#define pb push_back
#define mpi make_pair
#define fi first
#define se second
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define pi acos(-1)
using namespace std;
const int maxn=1e4+10;
const int mod=1e9+7;
const int INF=0x3f3f3f3f;
typedef long long ll;
inline ll lowbit(ll x){return x&(-x);}   
string ans[maxn]; 
string get(int x){
	string ans="";
	if(x==0) ans="zero";
	if(x==1) ans="one";
	if(x==2) ans="two";
	if(x==3) ans="three";
	if(x==4) ans="four";
	if(x==5) ans="five";
	if(x==6) ans="six";
	if(x==7) ans="seven";
	if(x==8) ans="eight";
	if(x==9) ans="nine";
	return ans;
}    
int main(){
	string s;
	ll sum=0;
	cin>>s;
	for(int i=0;i<s.length();i++){
		sum+=s[i]-'0';
	}
	if(sum==0) puts("zero");
	else{
		int cnt=0;
		while(sum){
			int k=sum%10;
			ans[cnt++]=get(k);
			sum/=10;
		}
		for(int i=cnt-1;i>=0;i--){
			cout<<ans[i];
			if(i==0) cout<<endl;
			else cout<<" ";
		}
	}
	return 0;	
}

简易版:

#include<bits/stdc++.h>
#define pb push_back
#define mpi make_pair
#define fi first
#define se second
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define pi acos(-1)
using namespace std;
const int maxn=1e4+10;
const int mod=1e9+7;
const int INF=0x3f3f3f3f;
typedef long long ll;
inline ll lowbit(ll x){return x&(-x);}   
string ans[10]={"zero","one","two","three","four","five","six","seven","eight","nine"}; 
int main(){
	string s;
	ll sum=0;
	cin>>s;
	for(int i=0;i<s.length();i++){
		sum+=s[i]-'0';
	}
	s=to_string(sum);
	cout<<ans[s[0]-'0'];
	for(int i=1;i<s.length();i++){
		cout<<" "<<ans[s[i]-'0'];
	}
	cout<<endl;
	return 0;	
}

1006 Sign In and Sign Out (25 分)

题目大意:

给出每个人进出机房的时间,求第一个进入机房的人和最后一个离开机房的人。

结构体排序或者直接比较大小,得出答案

#include<bits/stdc++.h>
#define pb push_back
#define mpi make_pair
#define fi first
#define se second
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define pi acos(-1)
using namespace std;
const int maxn=1e5+10;
const int mod=1e9+7;
const int INF=0x3f3f3f3f;
typedef long long ll;
inline ll lowbit(ll x){return x&(-x);}   
struct stu{
	string id;
	int t1,t2;
}s[maxn];
bool cmp1(stu a,stu b){
	return a.t1<b.t1;
}
bool cmp2(stu a,stu b){
	return a.t2>b.t2;
}
int main(){
	int n;
	cin>>n;
	for(int i=0;i<n;i++){
		int h1,m1,s1,h2,m2,s2;
		cin>>s[i].id;
		scanf("%d:%d:%d %d:%d:%d",&h1,&m1,&s1,&h2,&m2,&s2);
		s[i].t1=h1*3600+m1*60+s1;
		s[i].t2=h2*3600+m2*60+s2;
	}
	sort(s,s+n,cmp1);
	cout<<s[0].id;
	sort(s,s+n,cmp2);
	cout<<" "<<s[0].id<<endl;
	return 0;	
}

简易版

#include<bits/stdc++.h>
#define pb push_back
#define mpi make_pair
#define fi first
#define se second
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define pi acos(-1)
using namespace std;
const int maxn=1e5+10;
const int mod=1e9+7;
const int INF=0x3f3f3f3f;
typedef long long ll;
inline ll lowbit(ll x){return x&(-x);}   
int main(){
	int n;
	cin>>n;
	int mmin=INF,mmax=0;
	string unlock,lock;
	for(int i=0;i<n;i++){
		string id;
		int h1,m1,s1,h2,m2,s2;
		cin>>id;
		scanf("%d:%d:%d %d:%d:%d",&h1,&m1,&s1,&h2,&m2,&s2);
		int t1=h1*3600+m1*60+s1;
		if(t1<mmin){
			mmin=t1;
			unlock=id;
		}
		int t2=h2*3600+m2*60+s2;
		if(t2>mmax){
			mmax=t2;
			lock=id;
		}	
	}
	cout<<unlock<<" "<<lock<<endl;
	return 0;	
}

1007 Maximum Subsequence Sum (25 分)

题目大意:

求序列的连续子序列和的最大值,并输出该子序列的第一和最后一个元素

数据范围只有1e4,所有其实可以直接套两个循环,暴力求解。

暴力做法:

#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
const int maxn=1e5+10;
int a[maxn];
int main()
{ 
	int n;
	cin>>n;
	int flag=0;
	for(int i=1;i<=n;i++){
		cin>>a[i];
		if(a[i]>=0) flag=1;
	}
	if(!flag) cout<<"0 "<<a[1]<<" "<<a[n]<<endl;
	else{
		int mmax=0;
		int l=0,r=0;
		for(int i=1;i<=n;i++){
			int ans=0;
			for(int j=i;j<=n;j++){
				ans+=a[j];
				if(ans>mmax){
					mmax=ans;
					l=i;
					r=j;
				}
			}
		}
	    cout<<mmax<<" "<<a[l]<<" "<<a[r]<<endl;
	}
	return 0;
} 

其实我也不知道下面这种做法具体叫什么,只记得陈越姥姥在她的数据结构课上也讲过一个类似的题,就提到了在线处理的做法,感觉思想有点像。

#include<bits/stdc++.h>#define pb push_back#define mpi make_pair#define fi first#define se second#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);#define pi acos(-1)using namespace std;const int maxn=1e5+10;const int mod=1e9+7;const int INF=0x3f3f3f3f;typedef long long ll;inline ll lowbit(ll x){return x&(-x);}  int a[maxn]; int main(){	int n;	cin>>n;	int flag=0;	for(int i=0;i<n;i++){		cin>>a[i];		if(a[i]>=0) flag=1;	}	if(!flag){		cout<<"0 "<<a[0]<<" "<<a[n-1]<<endl;//看清楚自己的下标是从0还是1开始的,不要写错了呀!		return 0;	}	int sum=0;	int mmax=-1;//一定要初始化为-1,否则会出错!!	int l=0,r=0;	int idx=0;	for(int i=0;i<n;i++){		sum+=a[i];		if(sum>mmax){			mmax=sum;			l=idx;			r=i;		}		if(sum<0){			sum=0;			idx=i+1;		}	}	cout<<mmax<<" "<<a[l]<<" "<<a[r]<<endl;	return 0;	}

1008 Elevator (20 分)

题目大意:

电梯每上升一层需要花费6秒钟,每下降一层需要花费4秒钟,到达目的楼层后,还会在此楼层停留5秒钟。

给定一个目的楼层序列,问乘坐电梯依次到达这些楼层,总共需要花费的时间。

简单模拟,注意电梯最开始在第零层,所以当第一个目的楼层也是第零层时,就不用停留五秒钟。

#include<iostream>
#include<cstring>
#include<algorithm>
#include<set>
using namespace std;
typedef long long ll;
const int maxn=100005;
int a[maxn];
int main()
{
   int wait=0,up=0,down=0;
   int n;
   cin>>n;
   for(int i=0;i<n;i++){
   	   cin>>a[i];
   }
   wait=n*5;
   if(a[0]==0)
   wait-=5;
   up=a[0]*6;
   for(int i=0;i<n-1;i++){
   	   if(a[i+1]>a[i])
   	   up+=(a[i+1]-a[i])*6;
   	   else if(a[i+1]<a[i])
   	   down+=(a[i]-a[i+1])*4;
   }
   cout<<wait+up+down<<endl;
	return 0;
}

1009 Product of Polynomials (25 分)

题目大意:

模拟多项式乘法

系数相乘,指数相加

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=2e3+10;
struct exp{
	double c;
	int e;
}a[maxn];
double ans[maxn];
int main()
{
	int k1,k2;
	scanf("%d",&k1);
	for(int i=0;i<k1;i++){
		scanf("%d%lf",&a[i].e,&a[i].c);
	}
	scanf("%d",&k2);
	int n;
	double m;
	for(int i=0;i<k2;i++){
		scanf("%d%lf",&n,&m);
		for(int i=0;i<k1;i++){
			ans[n+a[i].e]+=m*a[i].c;
		}
	}
	int cnt=0;
	for(int i=maxn-1;i>=0;i--){
		if(ans[i]!=0) cnt++;
	}
	printf("%d",cnt);
	for(int i=maxn-1;i>=0;i--){
		if(ans[i]!=0) printf(" %d %.1lf",i,ans[i]);
	}
	printf("\n");
	return 0;
}

1010 Radix (25 分)

题目大意:

给出两个数字 N 1 N_1 N1 N 2 N_2 N2,并给定其中一个数字是几进制数,问能否找到另一个数在某进制下的值等于前一个数,若能输出是几进制,否则输出"Impossible".

十进制转化为任意进制:短除法

任意进制转化为10进制:每一位乘以该进制数的相应次幂

不管给定的是几进制数,都将其转化为十进制,之后比较大小,若相等,则输出答案;不想等,则不可能。

注:

数据范围: N 1 N_1 N1 N 2 N_2 N2都不超过10位数,每一位的可能取值为0-9,a-z(10-35)

但不能认为进制数的范围就是1进制到36进制。

N 1 N_1 N1 N 2 N_2 N2是36进制时的最大值可能是: 3 5 11 − 1 = 9654915737304688 0 ( 10 ) 35^{11}-1=96549157373046880_{(10)} 35111=96549157373046880(10),故需开long long

若出现:96549157373046880 10 1 10

则应输出:96549157373046880(进制)

所以进制数的范围其实是[1,96549157373046880],范围过大,不能暴力的遍历

==>使用二分(OlogN),极大的节省时间

如何确定一个数的最小进制是多少:该数各位数字中的最大值+1

而一个数的最大进制可能是其转化为10进制之后加1

当进制数过于大时,将其转化为10进制,将会发生溢出,所以如果出现进制转化结果小于0,也表明这个进制取的太大了。

#include<bits/stdc++.h>
#define pb push_back
#define mpi make_pair
#define fi first
#define se second
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define pi acos(-1)
using namespace std;
const int maxn=1e4+10;
const int mod=1e9+7;
const int INF=0x3f3f3f3f;
typedef long long ll;
inline ll lowbit(ll x){return x&(-x);}  
ll change(string s,ll k){//任意进制转十进制
	ll ans=0;
	for(int i=0;i<s.length();i++){
		if(isdigit(s[i])) ans=ans*k+s[i]-'0';
		if(isalpha(s[i])) ans=ans*k+s[i]-'a'+10;
	}
	return ans;
}
void find(string s,ll n){
	ll l=0;
	ll x; 
	for(int i=0;i<s.length();i++){//求最小可能进制
		if(isdigit(s[i])) x=s[i]-'0';
		if(isalpha(s[i])) x=s[i]-'a'+10;
		l=max(l,x);
	}
	l++;
	ll r=max(n,l);
	while(l<=r){//二分搜答案
		ll mid=(l+r)/2;
		ll t=change(s,mid);
		if(t==n){
			cout<<mid<<endl;
			return;
		}
		else if(t<0||t>n){
			r=mid-1;
		}
		else if(t<n){
			l=mid+1;
		}
	}
	puts("Impossible");	
}
int main(){
	string s,t;
	ll tag,rad;
	cin>>s>>t>>tag>>rad;
	if(tag==1) find(t,change(s,rad));
	else find(s,change(t,rad));
	return 0;	
}

1011 World Cup Betting (20 分)

题目大意:

找出每一行的最大值,依次输出该值所在列所代表的字母,并得到的所有最大值按照公式计算结果。

简单题

#include<bits/stdc++.h>
#define pb push_back
#define mpi make_pair
#define fi first
#define se second
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define pi acos(-1)
using namespace std;
const int maxn=1e4+10;
const int mod=1e9+7;
const int INF=0x3f3f3f3f;
typedef long long ll;
inline ll lowbit(ll x){return x&(-x);}  
char ch[]={"WTL"};
int main(){
	double ans=1.0;
	for(int i=0;i<3;i++){
		double mmax=0.0;
		int idx=0;
		for(int j=0;j<3;j++){
			double x;
			cin>>x;
			if(x>mmax){
				mmax=x;
				idx=j;
			}
		}
		printf("%c ",ch[idx]);
		ans*=mmax;
	}
	printf("%.2lf\n",(ans*0.65-1)*2);
	return 0;	
}

1012 The Best Rank (25 分)

题目大意:

给出每个学生的计算机成绩、数学成绩、英语成绩和平均分,分别进行排名。

询问某学生排名最好的哪一项,排多少名

结构体排序

首先预处理出每个学生的各科排名

1、用结构体存储学生的id、四项成绩

2、用二维数组存储相应id的某项成绩的排名

3、查询时,取四项成绩中排名最靠前的一项

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll maxn=1e7;
int j;
char course[4]={'A','C','M','E'};
int r[maxn][4];
struct stu{
	int id;
	int g[4];
}s[maxn];
bool cmp(stu a,stu b){
	return a.g[j]>b.g[j];
}
int main()
{
	
	int n,m;
	cin>>n>>m;
	for(int i=0;i<n;i++){
		cin>>s[i].id>>s[i].g[1]>>s[i].g[2]>>s[i].g[3];
		s[i].g[0]=s[i].g[1]+s[i].g[2]+s[i].g[3];
	}
	for(j=0;j<4;j++){
		sort(s,s+n,cmp);//按第j项成绩从高到低排序
		r[s[0].id][j]=1;
		for(int k=1;k<n;k++){
			if(s[k].g[j]==s[k-1].g[j])
			r[s[k].id][j]=r[s[k-1].id][j];
			else r[s[k].id][j]=k+1;
		}	
	}
	int q;
	for(int i=0;i<m;i++){
		cin>>q;
		if(r[q][0]==0)//不存在该学生
		cout<<"N/A\n";
		else{
			int min=0;
			for(int k=0;k<4;k++){
				if(r[q][k]<r[q][min])
				min=k;
			}
			cout<<r[q][min]<<" "<<course[min]<<endl;
		}
	}
	
	return 0;
}

1013 Battle Over Cities (25 分)

题目大意:

如果一座城市在战时被敌方攻占,则途经该城市的所有道路都将被破坏。

战后要确保整个国家中的任意城市依然可以通过道路连通,则需重建道路。若某城市被攻占,问战后需修建多少多少条道路。

需要修复的道路即连通块的个数减1

若城市i被攻占之后,仍只有一个连通块,则说明,无需重建道路;否则将剩下的所有连通块都连接起来,许哟啊重建的道路数量即为:连通块个数-1

1、邻接表存图

2、dfs跑连通块

#include<bits/stdc++.h>
#define pb push_back
#define mpi make_pair
#define fi first
#define se second
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define pi acos(-1)
using namespace std;
const int maxn=1e4+10;
const int mod=1e9+7;
const int INF=0x3f3f3f3f;
typedef long long ll;
inline ll lowbit(ll x){return x&(-x);}  
vector<int>e[maxn];//存图
int vis[maxn]; 
void dfs(int x){//跑连通块,能到的点,都标为1
	vis[x]=1;
	for(int i=0;i<e[x].size();i++){
		if(!vis[e[x][i]]) dfs(e[x][i]);
	} 
}
int main(){
	int n,m,k;
	cin>>n>>m>>k;
	while(m--){
		int u,v;
		cin>>u>>v;
		e[u].pb(v);
		e[v].pb(u);
	}
	while(k--){
		int x;
		cin>>x;
		memset(vis,0,sizeof(vis));
		vis[x]=1;
		int cnt=0;//记连通块个数
		for(int i=1;i<=n;i++){
			if(!vis[i]){
				dfs(i);
				cnt++;
			}
		}
		cout<<cnt-1<<endl;
	}
	return 0;	
}

1014 Waiting in Line (30 分)

题目大意:

银行一共有N个窗口提供服务。每个窗口前有一条黄线,将等候区分成两个部分。客户排队等候的规则如下:

1、黄线之前可以容纳M个客户,因此从第NM+1个客户开始,就要站在黄线之后排队等候。

2、进入黄线之前的客户,会选择当前排队人数最少的那个窗口。如果排队人数最少的窗口多于1个,客户将会选择序号小的那个窗口。

3、第i个客户会花费 T i T_i Ti分钟办理业务

4、银行从早上八点开始营业,下午五点关门。

现需查询轮到某客户开始办理业务的时间点,如果轮到该客户办理业务的时间已经超过 17 : 00 17:00 17:00,那么他不能再进行业务办理;如果能进行业务办理,直接输出该客户办理业务的时间即可。

当前客户办理业务的时间等于排在他前面那个客户完成业务办理的时间。

用结构体记录每个窗口接待客户的情况:

1、用队列queue记录该窗口当前的排队队列;

2、记录当前窗口队首客户办理完业务的时间(办理完业务,即可空出一个位置,让下一个人上来排队,这个人根据所有窗口队首客户办理完业务的时间来选择要去哪个窗口排队)

3、记录当前窗口队尾客户办理完业务的时间,其实也就知道了下一个到这个窗口排队的客户开始处理业务的时间。

4、对于开始办理业务的时间超过 17 : 00 17:00 17:00的客户,需要单独标记其状态。

就有点绕,一定要先理清楚,再写代码哦

#include<bits/stdc++.h>
#define pb push_back
#define mpi make_pair
#define fi first
#define se second
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define pi acos(-1)
using namespace std;
const int maxn=1e4+10;
const int mod=1e9+7;
const int INF=0x3f3f3f3f;
typedef long long ll;
inline ll lowbit(ll x){return x&(-x);}  
int cus[maxn];//客户办理业务所需时间
int ans[maxn];//客户办理完业务的时间
struct Windows{
	int early;//当前窗口队首客户办理完业务的时间
	int late;//当前窗口队尾客户办理完业务的时间
	queue<int>q;//当前窗口的排队队列
}w[maxn];
int main(){
	int n,m,k,q;
	cin>>n>>m>>k>>q;
	for(int i=1;i<=k;i++){
		cin>>cus[i];
	}
	int cnt=1;
 	vector<bool>sorry(k+1,false);//开始办理业务时间超过$17:00$的客户标为true
	for(int i=1;i<=m;i++){//前N*M个客户,直接上前排队
		for(int j=1;j<=n;j++){
			if(cnt<=k){
				w[j].q.push(cus[cnt]);//客户排入队伍
				if(w[j].late>=540){//如果当前窗口队尾客户办理完业务的时间已经超过$17:00$,那当前客户不能再进行业务办理
					sorry[cnt]=true;
				}
				w[j].late+=cus[cnt];//更新当前窗口队尾客户办理完业务的时间
				if(i==1) w[j].early=w[j].late;//当前窗口队首客户办理完业务的时间,就等于该窗口只有一个客户排队时办理完业务的时间
				ans[cnt]=w[j].late;//记录当前客户办理完业务的时间(此时该客户已经排入队伍)
				cnt++;	
			}
		}
	}
	while(cnt<=k){//从第N*M+1个客户开始,每个客户都要选择一个人数最少的窗口(直接看哪个窗口的队首客户最先办理完业务,最先空出一个位置)
		int mmin=w[1].early,pos=1;
		for(int i=2;i<=n;i++){
			if(w[i].early<mmin){
				mmin=w[i].early;
				pos=i;
			}
		}
		w[pos].q.pop();//当前窗口队首客户办理完业务并离开
		w[pos].q.push(cus[cnt]);//下一个客户填补空位
		w[pos].early+=w[pos].q.front();//更新当前窗口队首客户办理完业务的时间
		if(w[pos].late>=540) sorry[cnt]=true;
		w[pos].late+=cus[cnt]; //更新当前窗口队尾客户办理完业务的时间
		ans[cnt]=w[pos].late;
		cnt++;		
	} 
	while(q--){
		int x;
		cin>>x;
		if(sorry[x]) puts("Sorry");
		else{
			printf("%02d:%02d\n",(ans[x]+480)/60,(ans[x]+480)%60);//注意输出格式
		}
	}
	return 0;	
}

1015 Reversible Primes (20 分)

题目大意:

如果一个质数在D进制下反转后的数仍然是一个质数,则为可逆质数

试判断正整数N在D进制中是否为可逆质数。

题目一定不要读错呀!(读英文题注意"断句"!)

根据题意:
首先N要是一个质数,然后将N转化为D进制并反转,再判断这个数是不是质数(质数一定是十进制数,所以当然要先把反转后的数变成十进制)

#include<bits/stdc++.h>
#define pb push_back
#define mpi make_pair
#define fi first
#define se second
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define pi acos(-1)
using namespace std;
const int maxn=1e4+10;
const int mod=1e9+7;
const int INF=0x3f3f3f3f;
typedef long long ll;
inline ll lowbit(ll x){return x&(-x);}  
bool prime(ll x){
	if(x<2) return false;
	for(ll i=2;i*i<=x;i++){
		if(x%i==0) return false;
	}
	return true;
}
ll change(ll x,ll k){
	string s=""; 
	while(x){//转k进制
		s+=to_string(x%k);
		x/=k;		
	}
	ll ans=0;
	for(int i=0;i<s.length();i++){//转十进制
		ans=ans*k+s[i]-'0';
	}
	return ans;
}
int main(){
	ll n,k;
	while(cin>>n){
		if(n<0) break;
		cin>>k;
		ll m=change(n,k);
		if(prime(n)&&prime(m)) puts("Yes");
		else puts("No");
	}
	return 0;	
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值