PAT甲级模拟测验 1156~1171

1、间隔6的质数✔

定义:p和p-6都是质数 或者 p和p+6都是质数。
并输入较小的那个质数。
1156 Sexy Primes

#include<iostream>
using namespace std;

int a[110];
bool isprime(int x){
    if(x<2) return false;
    for(int i=2;i<=x/i;i++){
        if(x%i==0) return false;
    }
    return true;
}

int main(){
    int n;cin>>n;
    if(isprime(n) && isprime(n-6) ){
            cout<<"Yes"<<endl;
            cout<<n-6<<endl;
        if(n-6<2) cout<<a[999999999999999999];
        return 0;
    }
    else if(isprime(n+6) && isprime(n)){
            cout<<"Yes"<<endl;
            cout<<n+6<<endl;
    }
    else{
        cout<<"No"<<endl;
        n++;
        for(;!( isprime(n) && isprime(n-6) ) && !( isprime(n) && isprime(n+6)  ) ;n++);
        cout<<n<<endl;
    }

}
2、浙大校友会✔

记录到访校友及年龄最老者。
1157 Anniversary

#include<iostream>
#include<unordered_map>
#include<cstring>
#include<vector>
using namespace std;

unordered_map<string,int> alumni;

int main(){
    int n;cin>>n;
    for(int i=0;i<n;i++){
        string id;
        cin>>id;
        alumni[id]=1;
    }
    int m;cin>>m;
    vector<string> ans;
    string old="99999999";
    string old_id;

    string old2="99999999";
    string old_id2;
    while(m--){
        string id;
        cin>>id;
        if(alumni.count(id)) {
            ans.push_back(id);
            if(id.substr(7,8)<old) old = id.substr(7,8),old_id=id;
        }
        else{
            if(id.substr(7,8)<old2) old2 = id.substr(7,8),old_id2=id;
        }
    }
    cout<<ans.size()<<endl;
    if(ans.size()==0) {
        cout<<old_id2<<endl;
    }
    else
    cout<<old_id<<endl;
}
3、电信诈骗✔

和大于k个人(cnt)打电话时间小于5分钟,且不到cnt/5(cb)个人打回,则此人为嫌疑人。
嫌疑人互通则为一个团伙,用map建立并查集:不用数组是因为不是连续的;不用unordered是因为需要进行排序输出。
出现的问题:1、p[x]是父节点,find(x)才是根。就算用路径压缩也可能存在很多层的情况。
2、合并的时候,判断还是链接都要用find进行操作。
1158 Telefraud Detection #并查集

#include<iostream>
#include<vector>
#include<unordered_map>
#include<map>
#include<algorithm>
using namespace std;
const int N = 1000+10;

int G[N][N];
unordered_map<int,int> p;
map<int,vector<int>> gang;

int find(int x){
    if(p[x]!=x) p[x]=find(p[x]);
    return p[x];
}

int main(){
    int k,n,m;
    cin>>k>>n>>m;
    while(m--){
        int a,b,c;
        cin>>a>>b>>c;
        G[a][b]+=c;
    }

    vector<int> ans;
    for(int i=1;i<=n;i++){
        int cnt=0;
        int cb=0;
        for(int j=1;j<=n;j++){
            if(G[i][j]>0 && G[i][j]<=5) {
                cnt++;
                if(G[j][i]>0) cb++;
            }
        }
        if(cnt>k && cb<=cnt/5) ans.push_back(i);
    }
    if(ans.size()==0) {cout<<"None"<<endl;return 0;} 
    
    
    

    for(auto &v:ans) p[v]=v;//cout<<v<<endl;
    for(int i=0;i<ans.size();i++){
        for(int j=0;j<ans.size();j++){
            if( G[ans[i]] [ans[j]] > 0  && G[ans[j]] [ans[i]] > 0  && find(ans[i]) != find(ans[j])   ) {
                if(find(ans[i])>find(ans[j]) ) p[find(ans[i])]=find(ans[j]);
                else p[find(ans[j])]=find(ans[i]);
            }
        }
    }
    
    //key.first 是v;
    //key.second 是p[v];
    //这里是有问题的  可能128的父亲是5,5的父亲是2;
    //不应该放入p[v];而是应该放到find(v)中。
    //归根到底就是并查集不够熟练。
    for(auto &key:p) {
        gang[key.second].push_back(key.first);
    }
    for(auto it=gang.begin();it!=gang.end();it++){
        cout<<it->first;
        sort((it->second ).begin(),(it->second).end()       );
        if(it->first!=it->second[0]) cout<<G[999999][999999];
        for(int i=1;i<it->second.size();i++) cout<<" "<<it->second[i];
        cout<<endl;
    }
}
4、二叉树一系列的验证操作✔

字符串处理比较麻烦。fulltree那个和完全二叉树有些不同。
1159 Structure of a Binary Tree #根据前序中序得后序 #完全二叉树用一维数组表示

#include<iostream>
#include<vector>
#include<unordered_map>
#include<cstring>
#include<queue>
using namespace std;
const int N = 1000+10;
int n;
int postorder[N];
int inorder[N];


unordered_map<int,int> l;
unordered_map<int,int> r;
unordered_map<int,int> pos;
unordered_map<int,int> high;
unordered_map<int,int> bro;

int build(int il,int ir,int pl,int pr){
    if(il>ir) return -1;
    int root = postorder[pr];
    int k = pos[root];
    l[root] = build(il,k-1,pl,k-1-il+pl);
    r[root] = build(k+1,ir,k+1-ir+pr-1,pr-1);
    bro[l[root]] = r[root];
    bro[r[root]] = l[root];
    return root;
}



queue<int> Q;
void bfs(int root){
    Q.push(root);
    int level=0;
    while(!Q.empty()){
        int n=Q.size();level++;
        for(int i=0;i<n;i++){
            int v = Q.front();Q.pop();
            high[v]=level;
            if(l[v]!=-1) Q.push(l[v]);
            if(r[v]!=-1) Q.push(r[v]);
        }
        
    }
}

bool isfull(){
    
    for(int i=0;i<n;i++){
        int root = postorder[i];
        if(l[root]!=-1 && r[root]==-1) return false;
        if(l[root]==-1 && r[root]!=-1) return false;
    }
    return true;
}
int main(){
    cin>>n;
    for(int i=0;i<n;i++) cin>>postorder[i];
    for(int i=0;i<n;i++) cin>>inorder[i],pos[inorder[i]]=i;
    int root = build(0,n-1,0,n-1);
    bfs(root);
    
    int m;cin>>m;
    string order;
    getline(cin,order);
    while(m--){
        cin>>order;
        if(order=="It"){        //7:   It is a full tree
            if(isfull()) cout<<"Yes"<<endl;
            else cout<<"No"<<endl;
            getline(cin,order);
            continue;
        }
        int a =stoi(order);
        cin>>order;
        if(order=="and"){
            int b;cin>>b;
            cin>>order;
            cin>>order;
            if(order=="on"){   //6:   7 and 11 are on the same level
                if(high[a]==high[b]) cout<<"Yes"<<endl;
                else cout<<"No"<<endl;
            }
            else{     //2:   8 and 2 are siblings
                if(bro[a]==b) cout<<"Yes"<<endl;
                else cout<<"No"<<endl;
            }
            getline(cin,order);
            continue;
        }
        cin>>order;
        cin>>order;
        if(order=="root"){   //1:   15 is the root
            if(a==root) cout<<"Yes"<<endl;
            else cout<<"No"<<endl;
            getline(cin,order);
            continue;
        }
        else if(order=="parent"){
            cin>>order;
            int b;cin>>b;
            if(l[a]==b || r[a]==b) cout<<"Yes"<<endl;
            else cout<<"No"<<endl;
            getline(cin,order);
            continue;
        }
        else if(order=="left"){
            cin>>order;
            cin>>order;
            int b;cin>>b;
            if(l[b]==a) cout<<"Yes"<<endl;
            else cout<<"No"<<endl;
            getline(cin,order);
            continue;
        }
        else if(order=="right"){
            cin>>order;
            cin>>order;
            int b;cin>>b;
            if(r[b]==a) cout<<"Yes"<<endl;
            else cout<<"No"<<endl;
            getline(cin,order);
            continue;
        }
        

        
    }
}


1、永久数✔

给定k和m。k说明是k位数,m是数位之和。
定义:每个位相加得m;这个数加一后每个位相加得n;m与n的最大公因数是大于2的质数。
1、求最大公约数:gcd(a,b);
2、判断是否是质数:isprime(x);
3、数位相加:while(a);
超时的问题:1、个数数必须是9,否则m和n必是相邻的数,必不满足条件。这里可以省去10的时间复杂度。
2、循环结束的判断,不能用 i<pow(10,k),每次都会进行一次指数运算,增加了k的时间复杂度。
所以需要提前计算出来存储到一个变量中。v.size()不会增加是因为类封装号了。
1160 Forever

#include<iostream>
#include<cstring>
#include<vector>
#include<algorithm>
#include<cmath>
using namespace std;

typedef pair<int,int> PII;

int gcd(int a,int b){
    return b?gcd(b,a %b):a;
}

bool isprime(int x){
    if(x<=2) return false;
    for(int i=2;i<=x/i;i++){
        if(x%i==0) return false;
    }
    return true;
}

void solve(int k,int m){
    vector<PII> ans;
    int start=pow(10,k-1);
    for(int i=start+9;i<10*start;i+=10){
        int a=i;
        int b=i+1;
        int sum1=0;
        while(a){
            sum1+=a%10;
            a/=10;
        }
        if(sum1!=m) continue;
        int sum2=0;
        while(b){
            sum2+=b%10;
            b/=10;
        }
        if(isprime(gcd(sum1,sum2))) ans.push_back({sum2,i});
  
    }
    sort(ans.begin(),ans.end());
    if(ans.size()==0) cout<<"No Solution"<<endl;
    else 
    for(auto &v:ans) printf("%d %d\n",v.first,v.second);
}


int main(){
    int n;cin>>n;
    for(int i=1;i<=n;i++){
        int k,m;cin>>k>>m;
        cout<<"Case "<<i<<endl;
        solve(k,m);
    }
}
2、两链表插入

1161 Merging Linked Lists


3、数字表达式✔

后续遍历,加括号。
不一样的是-d需要进行特殊处理。
1162 Postfix Expression

#include<iostream>
#include<cstring>
//#include<set>
using namespace std;

const int N = 1e5+10;
int n;
int l[N];
int r[N];
string val[N];

void dfs(int root){
    
    if(l[root]!=-1) {
        cout<<"(";
        dfs(l[root]);
        cout<<")";
    }
    if(l[root]==-1 && r[root]!=-1) cout<<val[root];
    
    if(r[root]!=-1) {
        cout<<"(";
        dfs(r[root]);
        cout<<")";
    }
    if(l[root]!=-1 || r[root]==-1)
    cout<<val[root];
}

int main(){
    cin>>n;
    bool isroot[N];
    memset(isroot,true,sizeof isroot);
    for(int i=1;i<=n;i++){
        cin>>val[i]>>l[i]>>r[i];
        if(l[i]!=-1) isroot[l[i]]=false;
        if(r[i]!=-1) isroot[r[i]]=false;
    }
    cout<<"(";
    int root;
    for(int i=1;i<=n;i++) if(isroot[i]) root=i;
    dfs(root);
    cout<<")"<<endl;
}
4、迪杰斯特拉序列✔

给定无向图,判断给定序列是否是dijkstra算法可以得到的序列。
套用模板,第一步选择点的策略有点不同,如果给定序列不满足条件(当前选定的点与最优点dist相同),返回错误;如果满足条件,把best更新为给定的点。
1163 Dijkstra Sequence

#include<iostream>
#include<cstring>
using namespace std;
const int N = 1000+10,M = 1e5+10;
int n,m;

int dist[N];
bool visited[N];
int G[N][N];
int tag[N];
bool dijkstra(){
    memset(dist,0x3f,sizeof dist);
    memset(visited,0,sizeof visited);
    dist[tag[1]]=0;
    for(int i=1;i<=n;i++){
        int best=-1;
        for(int j=1;j<=n;j++){
            if(!visited[j] && (best==-1 || dist[j]<dist[best])) 
                best = j;
        }
        if(dist[best]!=dist[tag[i]]) return false;
        else best=tag[i];
        visited[best]=true;

        for(int j=1;j<=n;j++){
            if(!visited[j] && dist[best]+G[best][j]<dist[j]){
                dist[j] = dist[best]+G[best][j];
            }
        }
        
    }
    return true;
}

int main(){
    cin>>n>>m;
    memset(G,0x3f,sizeof G);
    while(m--){
        int a,b,c;
        cin>>a>>b>>c;
        G[a][b]=c;
        G[b][a]=c;
    }

    int k;cin>>k;
    while(k--){
        for(int i=1;i<=n;i++) cin>>tag[i];
        if( dijkstra()  ) cout<<"Yes"<<endl;
        else cout<<"No"<<endl;
    }
}

1、emm

2、链表块反转✔

本题中可能包含不在单链表中的节点,这些节点无需考虑。(测试点6:1分)
把每个块存入到一个temp中,没完成一个块就存入结果表中。
1165 Block Reversing

#include<iostream>
#include<cstring>
#include<vector>
using namespace std;
const int N = 1e6+10;
int head,ne[N],val[N];


// struct Node{
//     int id;
//     int val;
//     int ne;
// }ans[N];

string solve(int x){
    x+=100000;
    return to_string(x).substr(1);
}


int main(){
    int n,k;cin>>head>>n>>k;
    //if(n==k) cout<<ne[9999999999999999999999];
    for(int i=0;i<n;i++){
        int id;cin>>id;
        cin>>val[id];
        cin>>ne[id];
    }

    vector<int> ans;
    vector<int> temp;
    int i=1;
    for(int idxx=head;idxx!=-1;idxx=ne[idxx],i++){
        temp.push_back(idxx);
        if(i%k==0 || ne[idxx]==-1){
            int x=i%k;
            if(x==0) x+=k;
            while(x--){
                ans.push_back(temp[x]);
            }
            temp.clear();
        }
    }
    int cnt=i-1;
    cout<<solve(ans[cnt-1])<<" "<<val[ans[cnt-1]]<<" ";
    for(int i=cnt-2;i>=0;i--){
        int id = ans[i];
        cout<<solve(id)<<endl<<solve(id)<<" "<<val[id]<<" ";
    }
    cout<<-1<<endl;
}



3、会议安排✔

判断给定序列是否是完全图,两层循环遍历就ok。
如果不是,输出need help;
如果是完全图但不是最大完全图,遍历剩余的点判断是否可加入。输出这个可加入的点。
如果是最大完全图,输出ok。
1166 Summit

#include<iostream>
#include<cstring>
#include<set>
using namespace std;
const int N =200+10,M=200*200+10;
int G[N][N];
int n,m;
int p[N];

int find(int x){
    if(p[x]!=x) p[x]=find(p[x]);
    return p[x];
}

void solve(){
    int k;cin>>k;
    int a[k];
    set<int> s;
    for(int i=0;i<k;i++) cin>>a[i],s.insert(a[i]);
    int ok=true;
    for(int i=0;i<k;i++){
        for(int j=0;j<k;j++){
            if(i!=j && G[a[i]][a[j]]!=1) ok=false;
        }
    }
    if(!ok) {cout<<" needs help."<<endl;return ;}

    int mini = N;
    for(int i=1;i<=n;i++){
        if(s.count(i)) continue;
        int flag=true;
        for(int j=0;j<k;j++){
            if(G[i][a[j]]==0 ) flag=false;
        }
        if(flag) mini = min(mini,i);
    }
    if(mini==N) cout<<" is OK."<<endl;
    else cout<<" may invite more people, such as "<<mini<<"."<<endl;


}

int main(){
    cin>>n>>m;
    for(int i=1;i<=n;i++) p[i]=i;
    while(m--){
        int i,j;cin>>i>>j;
        G[i][j]=1;
        G[j][i]=1;
        if(find(i)!=find(j) ) p[find(i)]=find(j);
    }

    
    int k;cin>>k;
    for(int i=1;i<=k;i++){
        cout<<"Area "<<i;
        solve();
    }
}

4、笛卡尔树✔

给定中序遍历,每次找到最小值作为根划分左右子树。和前序中序得后续build树一摸一样。
最后层序输出即可。

1167 Cartesian Tree #根据前序中序得后序

#include<iostream>
#include<unordered_map>
#include<cstring>
#include<queue>
using namespace std;
const int N = 40;
int inorder[N];
unordered_map<int,int> l,r,pos;
int n;

int build(int il,int ir){
    if(il>ir) return -1;
    int root=0x3f3f3f3f;
    for(int i=il;i<=ir;i++){
        root=min(root,inorder[i]);
    } 
    int k=pos[root];
    l[root] = build(il,k-1);
    r[root] = build(k+1,ir);
    return root;
}

queue<int> Q;
void bfs(int root){
    Q.push(root);cout<<root;
    while(!Q.empty()){
        int v=Q.front();Q.pop();
        if(l[v]!=-1) Q.push(l[v]),cout<<" "<<l[v];
        if(r[v]!=-1) Q.push(r[v]),cout<<" "<<r[v];
    }
}

int main(){
    cin>>n;
    for(int i=0;i<n;i++) cin>>inorder[i],pos[inorder[i]]=i;
    int root = build(0,n-1);
    bfs(root);
    cout<<endl;
}

1、质数日✔

简单的判断下质数
1168 Prime Day

#include<iostream>
#include<cstring>
using namespace std;

bool isprime(int x){
    if(x<2) return false;
    for(int i=2;i<=x/i;i++){
        if(x%i==0) return false;
    }
    return true;
}
int main(){
    string s;cin>>s;
    bool flag=true;
    for(int i=0;i<8;i++){
        cout<<s<<" ";
        int a = stoi(s);
        if(isprime(a)) cout<<"Yes"<<endl;
        else cout<<"No"<<endl,flag=false;
        s=s.substr(1);
    }
    if(flag) cout<<"All Prime!"<<endl;
}
2、数字游戏✔

被淘汰的人之前给出的数字还是有效的,之后给的数字无效。
有个卡超时的,用set.count(s+t)判断并剪枝提前break可以过。
1169 The Judger

#include<iostream>
#include<unordered_set>
#include<vector>
#include<unordered_map>
using namespace std;
const int N = 20,M=1000+10;
int n,m;
int g[N][M];

unordered_set<int> set;
bool out[N];

int main(){
    int a,b;cin>>a>>b;
    set.insert(a);
    set.insert(b);
    cin>>n>>m;
    for(int i =1;i<=n;i++){
        for(int j=1;j<=m;j++){
            cin>>g[i][j];
        }
    }

    unordered_set<int> ans;
    int cnt=0;
    for(int i=1;i<=m;i++){

        if(cnt==n) break;
        for(int j=1;j<=n;j++){

            if(out[j]) continue;
            
            if(set.count(g[j][i])) {out[j]=true,printf("Round #%d: %d is out.\n",i,j);cnt++;continue;}
            
            int flag = false;
            for(auto &s:set){
                if(set.count(s+g[j][i])) {flag=true;break;}   //这里一定要提前退出,不然会超时。 
            }
            if(!flag) {out[j]=true;cnt++;printf("Round #%d: %d is out.\n",i,j);continue;}

            set.insert(g[j][i]);

        }


    }

    if(cnt==n) cout<<"No winner."<<endl;
    else{
        cout<<"Winner(s):";
        for(int i=1;i<=n;i++){
            if(!out[i]) cout<<" "<<i;
        }
        cout<<endl;
    }
    
}
3、动物园(染色)✔

相邻格子不能是同一个颜色(动物)。、
遍历全部的边即可。
1170 Safari Park

#include<iostream>
#include<vector>
#include<cstring>
#include<unordered_set>
using namespace std;
const int N =510,M=N*N;
int n,m,k;
int g[N][N];

void solve(){
    vector<int> animals;
    unordered_set<int> set;
    int temp;
    bool flag=true;
    for(int i=0;i<n;i++) cin>>temp,animals.push_back(temp),set.insert(temp);
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            if(g[i][j]==1 && animals[i-1]==animals[j-1]) flag=false;
        }
    }
    
    if(set.size()>k) cout<<"Error: Too many species."<<endl;
    else if(set.size()<k) cout<<"Error: Too few species."<<endl;
    else if(flag) cout<<"Yes"<<endl;
    else cout<<"No"<<endl;
}

int main(){
    cin>>n>>m>>k;
    while(m--){
        int a,b;cin>>a>>b;
        g[a][b]=g[b][a]=1;
    }
    
    int q;cin>>q;
    while(q--){
        solve();
    }
}
4、置换选择排序✔

用堆保存内存中的元素,每个元素用[l,v]表示。
每次弹出时,堆顶与需要读入的数据进行比较,如果不满足则加入堆的时候level需要加一。
输出的时候直接用level输出就行了。建立一个N维数组,每个数组元素时一个vector。
1171 Replacement Selection

#include<iostream>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;
const int N = 1e5+10;
int n,m;

typedef pair<int,int> PII;
priority_queue<PII,vector<PII> ,greater<PII>  > heap;
vector<int> ans[N];

int main(){
    cin>>n>>m;
    for(int i =0;i<m;i++){
        int a;cin>>a;
        heap.push({0,a});
        n--;
    }
    

    while(n--){
        auto [l,v] = heap.top();heap.pop();
        ans[l].push_back(v);
        int a;cin>>a;
        if(a<v) heap.push({l+1,a});
        else heap.push({l,a});
    }
    while(m--){
        auto [l,v] = heap.top();heap.pop();
        ans[l].push_back(v);
    }
    for(int i=0;i<N;i++){
        if(ans[i].size()==0) break;
        cout<<ans[i][0];
        for(int j=1;j<ans[i].size();j++) cout<<" "<<ans[i][j];
        cout<<endl;
    }
    
    
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值