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、两链表插入
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;
}
}