18.4.1 考试解题报告 P71
题目:https://files.cnblogs.com/files/lovewhy/problem.pdf
偷偷摘来dalao题面。
P71
竞赛时间:???? 年?? 月?? 日??:??-??:??
题目名称 | 智乃 | 麻耶 | 惠 |
名称 | kahuucino | zyougamaya | nacumegu |
输入 | kahuucino.in | zyougamaya.in | nacumegu.in |
输出 | kahuucino.out | zyougamaya.out | nacumegu.out |
每个测试点时限 | 1秒 | 1秒 | 1秒 |
内存限制 | 512MB | 512MB | 512MB |
测试点数目 | 20 | 10 | 10 |
每个测试点分值 | 5 | 10 | 10 |
是否有部分分 | 无 | 无 | 无 |
题目类型 | 传统 | 传统 | 传统 |
T1
智乃
【题目描述】
给你N个字符串,你每次可以选择其中一个字符串的一段前缀进行翻转,但是你必须保证这个前缀的长度是偶数。你可以进行无限次这样的操作,并且如果
两个字符串变得相同的时候,你就可以把这两个字符串都删除掉,问最后最少剩下多少个字符串?
【输入格式】
第一行一个整数T代表数据组数。
对于每组数据,第一行一个整数N代表字符串个数。
接下来N行每行一个字符串。
【输出格式】
对于每组数据,一行一个整数代表答案。
【样例输入】
2
5
esprit
god
redotopc
odcpoter
dog
14
rats
live
stressed
to
act
as
star
desserts
of
evil
cat
sa
fo
ot
【样例输出】
3
0
【样例解释】
无。
【数据范围与规定】
40%的数据,字符串长度不超过8。
对于100%的数据,1 ≤ T≤ 11,字符串长度不超过50,1 ≤ N ≤ 50。
T1
考场40分暴力:
开个结构体存字符串,然后bfs里暴力翻转,set判重,记录下来,最后n^4判断能不能消除。
前40分字符串长度<=8,翻转之后貌似是最多有384个串。
//T1 //这么难的吗??? //........ //暴力搞来一发 //1hour left //i am so nervous //不会写hash啊。。。老写炸。。 //那怎么判重啊/。。。 //Meide //trie树? //hhhh gg #include<iostream> #include<cstdio> #include<cmath> #include<cstring> #include<string> #include<algorithm> #include<queue> #include<set> using namespace std; const int N=55; int T,n; struct STR { bool flag; int len; int sum; string s; string ss[1000]; }str[N]; inline int read() { char c=getchar();int num=0,f=1; for(;!isdigit(c);c=getchar()) f=c=='-'?-1:f; for(;isdigit(c);c=getchar()) num=num*10+c-'0'; return num*f; } inline void mswap(char &a,char &b) { char c=a; a=b; b=c; } inline string reverse(string s,int a,int b) //stl的reverse不会用。。 { string tmp=s; for(;a<=b;++a,--b) { mswap(tmp[a],tmp[b]); } // cout<<"tmp: "<<tmp<<endl; return tmp; } set<string> ma; queue<string> que; void bfs(STR &A) { ma.clear(); ma.insert(A.s); que.push(A.s); string now,tmp; int len=A.len; while(!que.empty()) { now=que.front(); // cout<<now<<endl; que.pop(); for(int i=2;i<=len;++++i) { tmp=reverse(now,0,i-1); if(ma.count(tmp)) continue; que.push(tmp); A.ss[++A.sum]=tmp; ma.insert(tmp); } } } int main() { freopen("kahuucino.in","r",stdin); freopen("kahuucino.out","w",stdout); T=read(); while(T--) { n=read(); int ans=n; for(int i=1;i<=n;++i) str[i].flag=str[i].sum=0; for(int i=1;i<=n;++i) { cin>>str[i].s; // cout<<"aa: "<<str[i].s<<endl; str[i].ss[++str[i].sum]=str[i].s; str[i].len=str[i].s.length(); bfs(str[i]); } bool flag; // printf("%d",str[1].sum); for(int i=1;i<=n;++i) { if(str[i].flag) continue; for(int j=i+1;j<=n;++j) { if(str[j].flag||str[i].len!=str[j].len) continue; flag=0; for(int k=1;k<=str[i].sum;++k) { for(int l=1;l<=str[j].sum;++l) { if(str[i].ss[k]==str[j].ss[l]) { flag=1; str[i].flag=str[j].flag=1; ----ans; break; } } if(flag) break; } if(flag) break; } } printf("%d\n",ans); } return 0; }
// luogu-judger-enable-o2 //T1 正解 //为什么这么6的呢 //stl好用又简洁 //...代码真短 //因为不管怎么翻转,原串中挨着的两个字符第i和i+1个总挨在一起 //所以我们把原串分解成很多两个字母的组合 //让组合中的第一个字符的字典序<=第二个字符 //然后,把这好几个组合按字典序排序 //再把它们按排完序后的顺序组合起来 //set判断 //如果这个字符串以前出现过,那么就消掉,余下的字符串数量-2 //否则就扔进set里 //貌似好简单的对吧 //但是为什么就想不到呢 //只想着打暴力了 //想也不定能想出来 #include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<set> #include<vector> using namespace std; const int N=55; int T,n; set<string> se; string S[N]; string s[N]; string tmp; inline int work() { int len,ans=n; se.clear(); for(int i=1;i<=n;++i) { len=S[i].length(); for(int j=0;j*2<len;++j) { char x=S[i][j<<1],y=S[i][j<<1|1]; if(x>y) swap(x,y); s[j]=x,s[j]+=y; } sort(s,s+len/2); tmp.clear(); for(int j=0;j<len/2;++j) tmp+=s[j]; if(len&1) tmp+=S[i][len-1]; if(se.count(tmp)) { se.erase(tmp); ----ans; } else se.insert(tmp); } return ans; } string a; int main() { scanf("%d",&T); while(T--) { scanf("%d",&n); for(int i=1;i<=n;++i) cin>>S[i]; printf("%d\n",work()); } return 0; }
麻耶
【问题描述】
油库里是幻想乡特有的一种生物。每只油库里都有一个战斗力值和一个能量值。当两只油库里战斗时,总是战斗力值高的一位获胜。获胜者的战斗力值将变
成(自己的原战斗力值-对手的战斗力值+对手的能量值)。败者将死去。若两者战斗力值一样,则同归于尽。
思考熊发现了很多油库里,他想知道通过互相战斗之后油库里中战斗力值+能量值最高的一个可能到达多少。你能帮他们求出来吗?(假设除了考察的那只
油库里之外,其他油库里之间不会发生战斗)
【输入格式】
第一行是一个整数N,代表当前有多少油库里。
接下来的N行, 每一行有两个整数u,v, 代表这只油库里的战斗力值和能量值。
【输出格式】
输出一个整数,代表油库里中战斗力值+能量值最高的一个能达到多少。
【样例输入】
2
1 2
2 1
【样例输出】
4
【样例解释】
无。
【数据规模与约定】
数据点编号 | N = | 数据点编号 | N = |
1 | 2 | 6 | 14989 |
2 | 984 | 7 | 21726 |
3 | 6168 | 8 | 100000 |
4 | 10470 | 9 | 100000 |
5 | 19168 | 10 | 100000 |
T2
理解错题意,那些油库里不一定要死。十分。。。也很多吧。
天气炎热,不想改题。。
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> using namespace std; const int N=1e5+5; int n; long long ans,sum; struct Yuk { int u,v; bool operator < (const Yuk &a) const { return this->u==a.u?this->v>a.v:this->u<a.u; } }yuk[N]; inline int read() { char c=getchar();int num=0,f=1; for(;!isdigit(c);c=getchar()); f=c=='-'?-1:f; for(;isdigit(c);c=getchar()) num=num*10+c-'0'; return num*f; } int main() { n=read(); for(int i=1;i<=n;++i) { yuk[i].u=read(),yuk[i].v=read(); } sort(yuk+1,yuk+n+1); for(int i=1;i<=n;++i) { ans=max(ans,sum+yuk[i].u+yuk[i].v); if(yuk[i].u<yuk[i].v) sum+=yuk[i].v-yuk[i].u; } printf("%lld",ans); return 0; }
惠
【问题描述】
现在你要实现一个文件系统,支持以下操作
cd Directory_Name
如果当前路径下有名为 Directory_Name 的文件夹,则进入该文件夹所对应的路径,否则输出“No such directory!” 。
cd ..
如果当前路径存在父路径, 则返回父路径, 否则输出 “No parent directory!” 。
touch File_Name
如果当前目录下存在名为 File_Name 的文件则输出“File already exists!” ,否则创建这样一个文件。
rm File_Name
如果当前目录下存在名为 File_Name 的文件则删除它,否则输出“No suchfile!” 。
mkdir Directory_Nam e
如果在当前路径下存在名为 Directory_Name 的文件夹,则输出“Directoryalready exists!” ,否则创建这样一个文件夹(当前路径不变) 。
rmdir Directory_Name
如果在当前路径下存在名为 Directory_Name 的文件夹,则删除之,否则输出“No such directory!” 。
ls
列出当前路径下所有的文件和文件夹,每一项占一行,按创建的先后顺序给出。采用以下形式输:
“Item_Name Type” (Type 为 <D>(文件夹)或<F>(文件))
注意:同一路径下文件与文件夹可以同名,但同一路径下文件与文件、文件夹与文件夹不能同名。
初始时当前路径处于根路径下,无父路径。
【输入格式】
第一行为Q,表示有Q个操作。
接下来是Q行,每行输入为以上描述的操作之一。
【输出格式】
输出答案。
【样例输入】
3
mkdir standy
touch totalfrank
ls
【样例输出】
standy <D>
totalfrank <F>
【样例解释】
无。
【数据规模与约定】
对于100%的数据,1 ≤ Q ≤ 100,所有文件名字长度不超过200且均为小写字母。
T3
模拟
//耗我两个半小时。。made //写麻烦了,可以不开队列直接搞的 //没时间改了。。 //万一TLE //那就很TM了吧 //跑得真慢 //样例都这么慢 //等着翻车 //别翻车啊... //竟然A了。。。 //又长又丑的代码 //懒得改它了。 #include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<string> #include<stack> #include<queue> using namespace std; const int N=505; int Q; struct F { bool flag; int tim; string name; }file[N]; struct D { bool flag; //这个文件夹还在不在 int tim; //文件夹创建时间 string name; //文件夹名字 D *fa; //父亲path D *wjj[N]; //sons F *wj[N]; //file postions int s1,s2; //sum of dires and files D *q1[N]; F *q2[N]; int h1,h2,t1,t2; }dir[N<<1],Root; typedef D* W; W null,now_d,now; string opt,name; typedef F* H; H now_f; inline void init() { now_f=file; now_d=dir; now=&Root; now->h1=now->h2=1; now->t1=now->t2=0; now->fa=null; now->flag=1; now->name="Root"; } bool flag=0; W t1; H t2; int main() { freopen("nacumegu.in","r",stdin); freopen("nacumegu.out","w",stdout); init(); scanf("%d",&Q); for(int i=1;i<=Q;++i) { cin>>opt; // cout<<opt<<endl; if(opt=="ls") { // cout<<now->t1<<" "<<now->t2<<endl; // cout<<now->h1<<" "<<now->h2<<endl; while(1) { if(now->h1>now->t1||now->h2>now->t2) break; t1=now->q1[now->h1],t2=now->q2[now->h2]; if(t1->flag==0) { ++(now->h1); continue; } else if(t2->flag==0) { ++(now->h2); continue; } if(t1->tim<t2->tim) { cout<<t1->name<<" <D>"<<'\n'; ++(now->h1); } else { cout<<t2->name<<" <F>"<<'\n'; ++(now->h2); } } while(now->h1<=now->t1) { t1=now->q1[now->h1]; if(!t1->flag) { ++(now->h1); continue; } // printf("%s <D>\n",now->q1[now->h1]->name); cout<<t1->name<<" <D>"<<'\n'; ++(now->h1); } while(now->h2<=now->t2) { t2=now->q2[now->h2]; if(!t2->flag) { ++(now->h2); continue; } // printf("%s <F>\n",now->q2[now->h2]->name); cout<<t2->name<<" <F>"<<'\n'; ++(now->h2); } now->h1=now->h2=1; continue; } cin>>name; // cout<<opt<<" "<<name<<endl; if(opt=="cd") { if(name=="..") { if(now->fa==null) puts("No parent directory!"); else now=now->fa; } else { flag=0; for(int j=1;j<=now->s1;++j) { if(now->wjj[j]->flag&&now->wjj[j]->name==name) { now=now->wjj[j]; flag=1; break; } } if(!flag) puts("No such directory!"); } } else if(opt=="touch") { flag=0; for(int j=1;j<=now->s2;++j) { if(now->wj[j]->flag&&now->wj[j]->name==name) { flag=1; break; } } if(!flag) { ++now_f; now_f->flag=1; now_f->tim=i; now_f->name=name; now->wj[++now->s2]=now_f; now->q2[++now->t2]=now_f; } else puts("File already exists!"); } else if(opt=="rm") { flag=0; for(int j=1;j<=now->s2;++j) { if(now->wj[j]->flag&&now->wj[j]->name==name) { flag=1; now->wj[j]->flag=0; now->wj[j]->name=""; break; } } if(!flag) puts("No such file!"); } else if(opt=="mkdir") { flag=0; for(int j=1;j<=now->s1;++j) { if(now->wjj[j]->flag&&now->wjj[j]->name==name) { flag=1; break; } } if(flag) puts("Directory already exists!"); else { ++now_d; now_d->tim=i; now_d->fa=now; now_d->name=name; now_d->flag=1; now_d->h1=now_d->h2=1; now_d->t1=now_d->t2=0; now->wjj[++now->s1]=now_d; now->q1[++now->t1]=now_d; } } else if(opt=="rmdir") { flag=0; for(int j=1;j<=now->s1;++j) { if(now->wjj[j]->flag&&now->wjj[j]->name==name) { flag=1; now->wjj[j]->flag=0; now->wjj[j]->name=""; break; } } if(!flag) puts("No such directory!"); } } fclose(stdin); fclose(stdout); return 0; } /* 20 mkdir 123 cd 123 rm 123 cd .. rm 123 rmdir 12 rmdir 123 cd 123 ls */ /* 20 cd .. mkdir 123 mkdir 456 mk 123 mk 456 ls touch 123 touch 456 ls rmdir 456 mkdir 456 ls cd 123 ls touch mhe touch why cd .. ls */
做题顺序:
T1好难啊,不会。
T2好难啊,不会。
T3..模拟?。。好像很有意思,做一下。
T3 2.5h做完,给写的太麻烦了,可以很简洁的写完的。然后T2拿第一个点,然后剩下一小时搞T1,最后10min赵老师来让着交题,但我还没写完。然后继续强搞,在最后10min成功拿下T1的40分暴力分。 但是T2理解错题意,那10分并没有拿到。
得分:
T1 40
T2 0
T3 100
Sum 140
。。。。感觉这几天考的三场试都rp大爆发啊。但是今天的题目貌似并不难,可就是不会做。大概我深受一看不会就打暴力思想的影响吧,毕竟以前吃了考试老想正解不打暴力的很大的亏。但是一看不会就打暴力确实太暴力了。T2应该可以想出来的,但是T3模拟太耗了。 为什么总是不能比较让自己满意地做一套题呢。