今天开始PTA刷题记录,文章持续更新~
对于比较难的和有坑的题会有讲解
参考大佬文章:https
文章目录
- 1001 A+B Format (20 分)
- 1002 A+B for Polynomials (25 分)
- 1003 Emergency (25 分)
- 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 分)
- 1013 Battle Over Cities (25 分)
- 1014 Waiting in Line (30 分)
- 1015 Reversible Primes (20 分)
1001 A+B Format (20 分)
题目大意:计算a+b的值,以标准格数输出
莫得什么大问题,按要求来就好
#include<iostream>
using namespace std;
int s[10];
int main(){
int a,b;
cin>>a>>b;
int sum=a+b;
bool A=0;
if(sum<0){
sum*=(-1);
A=1;
}
if(sum==0) cout<<0;
int n=0;
while(sum){
s[++n]=sum%10;
sum/=10;
}
if(A) cout<<"-";
for(int i=n;i;i--){
cout<<s[i];
if(i==n-n%3+1&&n>=4) cout<<",";
if((i-(n-n%3+1))%3==0&&i/4>0&&i!=n-n%3+1) cout<<",";
}
return 0;
}
1002 A+B for Polynomials (25 分)
计算多项式A+B的和~
#include<iostream>
#include<stdio.h>
using namespace std;
double ans[1010]={0};
bool v[10100]={false};
int main(){
int k1,k2;
cin>>k1;
int a;
double k;
int num=0;
for(int i=0;i<k1;i++){
cin>>a>>k;
if(!v[a]&&k!=0.0){v[a]=1;num++;}
ans[a]+=k;
}
cin>>k2;
for(int i=0;i<k2;i++){
cin>>a>>k;
if(!v[a]&&k!=0.0){v[a]=1;num++;}
ans[a]+=k;
}
// cout<<v[0]<<endl;
cout<<num;
for(int i=1000;i>=0;i--){
if(ans[i]!=0 ) printf(" %d %.1f", i,ans[i]);
}
return 0;
}
1003 Emergency (25 分)
题目大意:n个城市m条路,每个城市有救援小组,所有的边的边权已知。给定起点和终点,求从起点到终点的最短路径条数以及最短路径上的救援小组数目之和。如果有多条就输出点权(城市救援小组数目)最大的那个
用一遍Dijkstra算法~救援小组个数相当于点权,用Dijkstra求边权最小的最短路径的条数,以及这些最短路径中点权最大的值~dis[i]表示从出发点到i结点最短路径的路径长度,num[i]表示从出发点到i结点最短路径的条数,w[i]表示从出发点到i点救援队的数目之和~当判定dis[u] + e[u][v] < dis[v]的时候,不仅仅要更新dis[v],还要更新num[v] = num[u], w[v] = weight[v] + w[u]; 如果dis[u] + e[u][v] == dis[v],还要更新num[v] += num[u],而且判断一下是否权重w[v]更小,如果更小了就更新w[v] = weight[v] + w[u];
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAX=550;
int n,m;
int a,b;
int d[MAX],g[MAX][MAX],c[MAX],num[MAX],w[MAX];
bool vis[MAX]={0};
void dis(){
memset(d,0x3f,sizeof d);
d[a]=0;
num[a]=1;
w[a]=c[a];
for(int i=0;i<n;i++){
int t=-1;
for(int j=0;j<n;j++){
if(!vis[j]&&(t==-1||d[t]>d[j]))
t=j;
}
vis[t]=1;
//cout<<t<<endl;
for(int j=0;j<n;j++){
if(vis[j] == 0&&d[j]>d[t]+g[t][j]){
num[j]=num[t];
w[j]=c[j]+w[t];
d[j]=d[t]+g[t][j];
}else if(d[j]==d[t]+g[t][j]){
num[j]+=num[t];
if(c[j]+w[t]>w[j]) w[j]=c[j]+w[t];
}
}
}
}
int main(){
cin>>n>>m;
cin>>a>>b;
for(int i=0;i<n;i++) cin>>c[i];
memset(g,0x3f,sizeof g);
while(m--){
int x,y,z;
cin>>x>>y>>z;
g[x][y]=g[y][x]=z;
}
dis();
cout<<num[b]<<" "<<w[b]<<endl;
return 0;
}
1005 Spell It Right (20 分)
题目大意:
讲一串数的每一个数相加,输出结果每一个数对应的英文
#include<iostream>
using namespace std;
void Eng(int x){
if(x==0) cout<<"zero";
else if(x==1) cout<<"one";
else if(x==2) cout<<"two";
else if(x==3) cout<<"three";
else if(x==4) cout<<"four";
else if(x==5) cout<<"five";
else if(x==6) cout<<"six";
else if(x==7) cout<<"seven";
else if(x==8) cout<<"eight";
else cout<<"nine";
}
int main(){
string s;
cin>>s;
int n=s.size();
int sum=0;
for(int i=0;i<n;i++){
sum+=(int)(s[i]-'0');
}
int mm=0,summ=sum;
while(summ){summ/=10;mm++;}
int m=1;
for(int i=1;i<mm;i++) m*=10;
//cout<<sum<<" "<<m<<endl;
while(sum||m){
int k=sum/m;
Eng(k);
sum=sum%m;
m/=10;
if(m) cout<<" ";
}
return 0;
}
1006 Sign In and Sign Out (25 分)
给出图书馆的时间和离开图书馆的时间,输出最早到和最晚离开的人
#include <iostream>
using namespace std;
int main(){
string open_id,open_time;
string close_id,close_time;
int m;
cin >> m;
for(int i = 0;i < m ; i ++){
string id, in_time , out_time;
cin >> id >> in_time >> out_time;
if(!i || open_time > in_time) {
open_time = in_time;
open_id = id;
}
if(!i || close_time < out_time) {
close_time = out_time;
close_id = id;
}
}
cout << open_id << ' ' << close_id;
}
1007 Maximum Subsequence Sum (25 分)(最大子序列和)
//最大子序列和
#include<iostream>
using namespace std;
int a[100086];
int main(){
int n;
cin>>n;
int m=0;
for(int i=0;i<n;i++){
cin>>a[i];
if(a[i]<0) m++;
}
if(m==n){
cout<<0<<" "<<a[0]<<" "<<a[n-1];
return 0;
}
long long maxx=a[0],l=a[0],r=a[0];
for(int i=0;i<n;i++){
int s=0;
for(int j=i;j<n;j++){
s+=a[j];
if(s>maxx){
maxx=s;
l=a[i];
r=a[j];
}
}
}
cout<<maxx<<" "<<l<<" "<<r<<endl;
return 0;
}
1008 Elevator (20 分)
坐电梯,按要求就好
#include<iostream>
using namespace std;
int a[10086];
int main(){
int n;
cin>>n;
long long sum=n*5;
for(int i=0;i<n;i++){
cin>>a[i];
if(!i) sum+=6*a[i];
else{
if(a[i]>a[i-1]) sum+=(a[i]-a[i-1])*6;
else if(a[i]==a[i-1]) sum+=0;
else sum+=(a[i-1]-a[i])*4;
}
}
cout<<sum<<endl;
}
1009 Product of Polynomials (25 分)
模拟多项式乘法
#include<iostream>
using namespace std;
int ae[10086],be[10086];
double ac[10086],bc[10086];
double ans[10086];
int main(){
int n,m;
cin>>n;
for(int i=0;i<n;i++) cin>>ae[i]>>ac[i];
cin>>m;
for(int i=0;i<m;i++) cin>>be[i]>>bc[i];
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
int sum=0;
sum=ae[j]+be[i];
ans[sum]+=ac[j]*bc[i];
// cout<<sum<<ac[j]*be[i]<<" "<<ac[j]<<" "<<bc[i]<<endl;
}
}
int k=0;
for(int i=2000;i>=0;i--){
if(ans[i]!=0.0) k++;
}
cout<<k;
for(int i=2000;i>=0;i--){
if(ans[i]!=0.0) printf(" %d %.1lf",i,ans[i]);
}
return 0;
}
1010 Radix (25 分)(大坑)
题目大意:给定n1、n2两个数,求可以是两者相等的进制;如果没有,输出Impossible
原来,我以为只是一个进制转换问题、、、
(十分钟后)
原来,还有溢出、、、、
(又十分钟后)
原来,还有超出十的特殊判断、、、
(再过了十分钟后)
原来,还有查找时速度太慢,超时的问题(最小进制范围应该是n2当中出现的最大数字+1,最大进制范围应该是取n1的值和n2当中出现的最大数字+1大的那一个)然后进行二分查找、、、
#include<iostream>
using namespace std;
#define int long long int
int jinshi(string s,int k){
int sum=0,m=1;
for(int i=s.size()-1;i>=0;i--){
if(isdigit(s[i])){sum+=(int)(s[i]-'0')*m;m*=k;}
else{sum+=(int)(s[i]-'a'+10)*m;m*=k;}
}
return sum;
}
int find(int l,int r,int n,string s){
int m;
while(l<=r){
int mid=(l+r)/2;
m=jinshi(s,mid);
//cout<<m<<" "<<n<<" "<<mid<<" "<<s<<endl;
if(m==n) return mid;
if(m>n||m<0) r=mid-1;
else l=mid+1;
}
return -1;
}
signed main(){
string n1,n2;
int t,r;
cin>>n1>>n2>>t>>r;
if(n1==n2){cout<<r;return 0;}
if(t==2) swap(n1,n2);
int a=jinshi(n1,r);
int minn=0,maxx;
for(int i=0;i<n2.size();i++){
if(isdigit(n2[i])){
if((int)(n2[i]-'0'+1)>minn) minn=(int)(n2[i]-'0'+1);
}else{
if((int)(n2[i]-'a'+1)>minn) minn=(int)(n2[i]-'a'+11);
//cout<<"z"<<endl;
}
}
maxx=max(minn,a);
//cout<<maxx<<" "<<minn<<endl;
int ans=find(minn,maxx,a,n2);
if(ans==-1) cout<<"Impossible";
else cout<<ans;
}
1011 World Cup Betting (20 分)
按要求做就好
#include<iostream>
#include<algorithm>
using namespace std;
struct sz{
int n;
double m;
}a[4];
int cmp(sz x,sz y){
return x.m>y.m;
}
int main(){
double sum=1;
for(int i=0;i<3;i++){
cin>>a[0].m>>a[1].m>>a[2].m;
a[0].n=1,a[1].n=2,a[2].n=3;
sort(a,a+3,cmp);
sum*=a[0].m;
if(a[0].n==1) cout<<"W ";
else if(a[0].n==2) cout<<"T ";
else cout<<"L ";
}
sum=(sum*0.65-1)*2;
printf("%.2lf",sum);
return 0;
}
1013 Battle Over Cities (25 分)
给出n个城市之间有相互连接的m条道路,当删除一个城市和其连接的道路的时候,问其他几个剩余的城市至少要添加多少个路线才能让它们重新变为连通图。
分析:当删掉城市时,与它相连的所有城市都要失去联系,然后遍历剩下的城市看它们分为互不练习的n个部分,答案就是n-1;
考点:邻接矩阵存图
#include<iostream>
#include<cstring>
using namespace std;
int n,m,k;
const int MAX=1011;
bool g[MAX][MAX],v[MAX];
void dfs(int x){
for(int i=1;i<=n;i++){
if(v[i]!=1&&g[x][i]){
v[i]=1;
dfs(i);
}
}
}
int main(){
ios::sync_with_stdio(false);
cin>>n>>m>>k;
memset(g,0,sizeof g);
while(m--){
int x,y;
cin>>x>>y;
g[x][y]=g[y][x]=1;
}
while(k--){
int x;
cin>>x;
int ans=0;
memset(v,0,sizeof v);
v[x]=1;
for(int i=1;i<=n;i++){
if(v[i]==0){dfs(i);ans++;}
}
cout<<ans-1;
if(k!=0) cout<<endl;
}
return 0;
}
1014 Waiting in Line (30 分)
题目大意::n个窗口,每个窗口可以排队m人。有k位用户需要服务,给出了每位用户需要的minute数,所有客户在8点开始服务,如果有窗口还没排满就入队,否则就在黄线外等候。如果有某一列有一个用户走了服务完毕了,黄线外的人就进来一个。如果同时就选窗口数小的。求q个人的服务结束时间。
如果一个客户在17:00以及以后还没有开始服务(此处不是结束服务是开始17:00)就不再服务输出sorry;如果这个服务已经开始了,无论时间多长都要等他服务完毕。
分析:
设立结构体,里面包含poptime为队首的人出队(结束)的时间,和endtime为队尾的人结束的时间。poptime是为了让黄线外的人可以计算出哪一个队列先空出人来(poptime最小的那个先有人服务完毕),endtime是为了入队后加上自己本身的服务所需时间可以计算出自己多久才能被服务完毕~且前一个人的endtime可以得知自己是不是需要被Sorry(如果前一个人服务结束时间超过17:00,自己当前入队的人就是sorry),还有一个queue表示所有当前该窗口的排队队列。
对于前mn个人,也就是排的下的情况下,所有人依次到窗口前面排队。对于mn之后的人,当前人选择poptime最短的入队,让队伍的第一个人出列),如果前面一个人导致的endtime超过17点就标记自己的sorry为true
#include<iostream>
#include<vector>
#include<queue>
using namespace std;
int a[1100];
struct que{
int poptime,endtime;
queue<int> q;
};
int main(){
int n,m,k,q,index=1;
cin>>n>>m>>k>>q;
for(int i=1;i<=k;i++) cin>>a[i];
vector<int> result(k+1);
vector<que> window(n+1);
vector<bool> sorry(k+1,false);
for(int i=1;i<=m;i++){
for(int j=1;j<=n;j++){
if(index<=k){
window[j].q.push(a[index]);
if(window[j].endtime>=540) sorry[index]=true;
window[j].endtime+=a[index];
if(i==1) window[j].poptime=window[j].endtime;
result[index]=window[j].endtime;
index++;
}
}
}
while(index<=k){
int tempmin=window[1].poptime,tempwindow=1;
for(int i=2;i<=n;i++){
if(window[i].poptime<tempmin){
tempmin=window[i].poptime;
tempwindow=i;
}
}
window[tempwindow].q.pop();
window[tempwindow].q.push(a[index]);
window[tempwindow].poptime+=window[tempwindow].q.front();
if(window[tempwindow].endtime>=540) sorry[index]=true;
window[tempwindow].endtime+=a[index];
result[index]=window[tempwindow].endtime;
index++;
}
for(int i=1;i<=q;i++){
int query,minu;
cin>>query;
minu=result[query];
if(sorry[query]==true){
cout<<"Sorry"<<endl;
}else{
printf("%02d:%02d\n",(minu+480)/60,(minu+480)%60);
}
}
return 0;
}
1015 Reversible Primes (20 分)
一直WA了第二组数据,结果是因为,0,1,不是素数。。。
#include<iostream>
#include<cstring>
#include<math.h>
using namespace std;
const int N=10010000;
int str[N],str_n;
void jinzhi(int k,int x){
while(x){
int m=x%k;
str[str_n++]=m;
x/=k;
}
return;
}
int zhuan(int k){
int sum=0,m=1;
for(int i=str_n-1;i>=0;i--){
sum+=str[i]*m;
m*=k;
}
return sum;
}
bool pri(int x){
//0,1不算质数
if(x==0||x==1) return false;
for(int i=2;i<=sqrt(x);i++){
if(x%i==0) return false;
}
return true;
}
int main(){
int n,d;
while(cin>>n){
memset(str,0,sizeof str);
str_n=0;
if(n<0) return 0;
cin>>d;
if(!pri(n)){cout<<"No"<<endl;continue;}
jinzhi(d,n);
int m=zhuan(d);
//cout<<m<<endl;
if(!pri(m)){cout<<"No"<<endl;continue;}
else cout<<"Yes"<<endl;
}
return 0;
}