9.5noip模拟试题
题目名称 |
正确答案 |
序列问题 |
长途旅行 |
英文名称 |
answer |
sequence |
travel |
输入文件名 |
answer.in |
sequence.in |
travel.in |
输出文件名 |
answer.out |
sequence.out |
travel.out |
时间限制 |
1s |
1s |
1s |
空间限制 |
256M |
256M |
256M |
测试点数目 |
20 |
20 |
10 |
测试点分值 |
5 |
5 |
10 |
是否有部分分 |
无 |
无 |
无 |
题目类型 |
传统 |
传统 |
传统 |
是否有SPJ |
无 |
无 |
无 |
1.正确答案
【题目描述】
小H与小Y刚刚参加完UOIP外卡组的初赛,就迫不及待的跑出考场对答案。
“吔,我的答案和你都不一样!”,小Y说道,”我们去找神犇们问答案吧”。
外卡组试卷中共有m道判断题,小H与小Y一共从其他n个神犇那问了答案。之后又从小G那里得知,这n个神犇中有p个考了满分,q个考了零分,其他神犇不为满分或零分。这可让小Y与小H犯了难。你能帮助他们还原出标准答案吗?如有多解则输出字典序最小的那个。无解输出-1。
【输入格式】
第一行四个整数n, m, p, q,意义如上描述。
接下来n行,每一行m个字符’N’或’Y’,表示这题这个神犇的答案。
【输出格式】
仅一行,一个长度为m的字符串或是-1。
【样例输入】
2 2 2 0
YY
YY
【样例输出】
YY
【数据范围】
30% : n <= 100.
60% : n <= 5000 , m <= 100.
100% : 1 <= n <= 30000 , 1 <= m <= 500. 0 <= p , q 且 p + q <= n.
暴力50:
- /*
- 自己还是太弱~没看出来要用hash 只是觉得自己的作法慢~
- QAQ
- 50分暴力 先排序 一样的缩成一种 然后枚举正确答案是哪个
- q==0 p==0的情况没考虑到~
- */
- #include<iostream>
- #include<cstdio>
- #include<cstring>
- #include<algorithm>
- #define maxn 30010
- #define maxm 510
- using namespace std;
- int n,m,p,q,cnt;
- string g[maxn];
- struct node{
- int len;
- string s;
- }k[maxn];
- int cmp(int a[maxm],int b[maxm]){
- for(int i=;i<=m;i++){
- if(a[i]<b[i])return ;
- if(a[i]>b[i])return ;
- }
- return ;
- }
- int main()
- {
- freopen("answer.in","r",stdin);
- freopen("answer.out","w",stdout);
- scanf("%d%d%d%d",&n,&m,&p,&q);
- for(int i=;i<=n;i++)cin>>g[i];
- sort(g+,g++n);
- int l=,r;
- for(r=;r<=n;r++){
- if(g[r]==g[l])continue;
- k[++cnt].s=g[l];
- k[cnt].len=r-l;l=r;
- }
- k[++cnt].s=g[l];
- k[cnt].len=r-l;
- int falg=;
- for(int i=;i<=cnt;i++){
- if(k[i].len!=p)continue;
- int sum=;
- string x;x.clear();
- for(int j=;j<m;j++)
- if(k[i].s[j]=='Y')x+='N';
- else x+='Y';
- for(int j=;j<=cnt;j++)
- if(k[j].s==x){
- sum+=k[j].len;
- break;
- }
- if(sum==q){
- cout<<k[i].s;
- falg=;break;
- }
- }
- if(falg==)
- for(int i=;i<=cnt;i++){
- if(k[i].len!=q)continue;
- int sum=;
- string x;x.clear();
- for(int j=;j<m;j++)
- if(k[i].s[j]=='Y')x+='N';
- else x+='Y';
- for(int j=;j<=cnt;j++)
- if(k[j].s==x){
- sum+=k[j].len;
- break;
- }
- if(sum==p){
- cout<<x;
- falg=;break;
- }
- }
- if(!falg)printf("-1\n");
- return ;
- }
正解hash:
- /*
- 正解hash
- 思路和之前的有相似之处
- 先排序 只不过没有类似离散化的处理
- 把每个人的答案放入hash表 这里用链表处理了碰撞的情况
- 然后同样的枚举正确答案 这不过用了hash表加速
- 对于pq==0的情况 枚举答案 按字典序小的来
- 那难道不会T到飞吗 不成了2^500的了吗
- 答案是不会的 这里的枚举是针对pq==0的情况来的
- 结束的条件是 找到与每个人都不一样的(存在一个即可)的就停下
- 所以枚举最多30000次
- */
- #include<iostream>
- #include<cstdio>
- #include<cstring>
- #include<algorithm>
- #define maxn 100010
- #define mod 10007
- #define MOD 23333
- #define bas 19
- #define BAS 119
- using namespace std;
- int n,m,p,q,hash[maxn],HASH[maxn],ans,falg;
- int num,head[maxn],cnt[maxn],t,T;
- struct edge{
- int v,pre;
- }e[maxn*];
- struct node{
- char s[];
- bool operator < (const node &x) const {
- return strcmp(s,x.s)<;
- }
- }a[maxn];
- void Insert(int from,int to){
- for(int i=head[from];i;i=e[i].pre)
- if(e[i].v==to){
- cnt[i]++;return;
- }
- num++;e[num].v=to;
- e[num].pre=head[from];
- head[from]=num;
- cnt[num]++;
- }
- int Query(int from,int to){
- for(int i=head[from];i;i=e[i].pre)
- if(e[i].v==to)return cnt[i];
- return ;
- }
- void Yan(){
- for(int i=;i<=n;i++){
- t=,T=;
- for(int j=;j<m;j++){
- t=t*bas+(a[i].s[j]=='Y');t%=mod;
- T=T*BAS+(a[i].s[j]=='Y');T%=MOD;
- }
- hash[i]=t;HASH[i]=T;
- Insert(t,T);
- }
- for(int i=;i<=n;i++){
- if(Query(hash[i],HASH[i])==p){
- int t=,T=;
- for(int j=;j<m;j++){
- t=t*bas+(a[i].s[j]=='N');t%=mod;
- T=T*BAS+(a[i].s[j]=='N');T%=MOD;
- }
- if(Query(t,T)==q){
- ans=i;
- falg=;break;
- }
- if(falg)break;
- }
- }
- if(falg)printf("%s\n",a[ans].s);
- else printf("-1\n");
- }
- void Li(){
- for(int i=;i<=n;i++){
- int t=,T=;
- for(int j=;j<m;j++){
- t=t*bas+(a[i].s[j]=='Y');t%=mod;
- T=T*BAS+(a[i].s[j]=='Y');T%=MOD;
- }
- hash[i]=t;HASH[i]=T;
- Insert(t,T);
- }
- for(int i=n;i>=;i--){
- if(Query(hash[i],HASH[i])==q){
- t=,T=;
- for(int j=;j<m;j++){
- t=t*bas+(a[i].s[j]=='N');t%=mod;
- T=T*BAS+(a[i].s[j]=='N');T%=MOD;
- }
- if(Query(t,T)==p){
- ans=i;
- falg=;break;
- }
- if(falg)break;
- }
- }
- if(falg){
- for(int i=;i<m;i++)
- if(a[ans].s[i]=='N')printf("Y");
- else printf("N");
- }
- else printf("-1\n");
- }
- void Feng(){
- for(int i=;i<=n;i++){
- t=,T=;
- for(int j=;j<m;j++){
- t=t*bas+(a[i].s[j]=='Y');t%=mod;
- T=T*BAS+(a[i].s[j]=='Y');T%=MOD;
- }
- Insert(t,T);
- t=;T=;
- for(int j=;j<m;j++){
- t=t*bas+(a[i].s[j]=='N');t%=mod;
- T=T*BAS+(a[i].s[j]=='N');T%=MOD;
- }
- Insert(t,T);
- }
- char r[];
- for(int i=;i<m;i++)r[i]='N';
- while(){
- t=,T=;
- for(int i=;i<m;i++){
- t=t*bas+(r[i]=='Y');t%=mod;
- T=T*BAS+(r[i]=='Y');T%=MOD;
- }
- if(Query(t,T)==){
- falg=;break;
- }
- for(int i=m-;i>=;i--)
- if(r[i]=='Y')r[i]='N';
- else{
- r[i]='Y';break;
- }
- }
- if(falg)printf("%s\n",r);
- else printf("-1\n");
- }
- int main()
- {
- freopen("answer.in","r",stdin);
- freopen("answer.out","w",stdout);
- scanf("%d%d%d%d",&n,&m,&p,&q);
- for(int i=;i<=n;i++)
- scanf("%s",a[i].s);
- sort(a+,a++n);
- if(p)Yan();
- else if(q)Li();
- else Feng();
- return ;
- }
2.序列问题
【题目描述】
小H是个善于思考的学生,她正在思考一个有关序列的问题。
她的面前浮现出了一个长度为n的序列{ai},她想找出两个非空的集合S、T。
这两个集合要满足以下的条件:
1. 两个集合中的元素都为整数,且都在 [1, n] 里,即Si,Ti ∈ [1, n]。
2. 对于集合S中任意一个元素x,集合T中任意一个元素y,满足x < y。
3. 对于大小分别为p, q的集合S与T,满足
a[s1] xor a[s2] xor a[s3] ... xor a[sp] = a[t1] and a[t2] and a[t3] ... and a[tq].
小H想知道一共有多少对这样的集合(S,T),你能帮助她吗?
【输入格式】
第一行,一个整数n
第二行,n个整数,代表ai。
【输出格式】
仅一行,表示最后的答案。
【样例输入】
4
1 2 3 3
【样例输出】
4
【样例解释】
S = {1,2}, T = {3}, 1 ^ 2 = 3 = 3 (^为异或)
S = {1,2}, T = {4}, 1 ^ 2 = 3 = 3
S = {1,2}, T = {3,4} 1 ^ 2 = 3 & 3 = 3 (&为与运算)
S = {3}, T = {4} 3 = 3 = 3
【数据范围】
30%:
1 <= n <= 10
60%:
1 <= n <= 100
100%:
1 <= n <= 1000, 0 <= ai < 1024
- /*
- 30分暴力枚举集合不说了
- 其实这题需要高精的....
- 维护i到n &值为j的方案数
- 维护1到i ^值为j的方案数
- 然后枚举断点 乘起来
- */
- #include<iostream>
- #include<cstdio>
- #include<cstring>
- #define maxn 2050
- #define ll long long
- using namespace std;
- ll n,a[maxn],b[maxn],sum[maxn],f[maxn][maxn+],g[maxn][maxn+],ans;
- int main()
- {
- freopen("sequence.in","r",stdin);
- freopen("sequence.out","w",stdout);
- cin>>n;
- for(ll i=;i<=n;i++)
- cin>>a[i];
- for(ll i=;i<=n;i++)
- b[i]=a[n-i+];
- for(ll i=;i<=n;i++){
- for(ll j=;j<=;j++)
- f[i][j]=sum[j^a[i]];
- f[i][a[i]]++;
- for(ll j=;j<=;j++)
- sum[j]+=f[i][j];
- }
- memset(sum,,sizeof(sum));
- for(ll i=;i<n;i++){
- for(ll j=;j<=;j++)
- g[i+][j&b[i+]]+=sum[j];
- g[i+][b[i+]]++;
- for(ll j=;j<=;j++)
- sum[j]+=g[i+][j];
- }
- memset(sum,,sizeof(sum));
- for(ll i=;i<n;i++){
- for(ll j=;j<;j++)
- sum[j]+=f[i][j];
- for(ll j=;j<;j++)
- ans+=sum[j]*g[n-i][j];
- }
- cout<<ans;
- return ;
- }
3.长途旅行
【题目描述】
JY是一个爱旅游的探险家,也是一名强迫症患者。现在JY想要在C国进行一次长途旅行,C国拥有n个城市(编号为0,1,2...,n - 1),城市之间有m条道路,可能某个城市到自己有一条道路,也有可能两个城市之间有多条道路,通过每条道路都要花费一些时间。JY从0号城市开始出发,目的地为n – 1号城市。由于JY想要好好参观一下C国,所以JY想要旅行恰好T小时。为了让自己的旅行更有意思,JY决定不在任何一个时刻停留(走一条到城市自己的路并不算停留)。JY想知道是否能够花恰好T小时到达n – 1号城市(每个城市可经过多次)。现在这个问题交给了你。
若可以恰好到达输出“Possible”否则输出“Impossible”。(不含引号)。
【输入格式】
第一行一个正整数Case,表示数据组数。
每组数据第一行3个整数,分别为n, m, T。
接下来m行,每行3个整数x, y, z,代表城市x和城市y之间有一条耗时为z的双向边。
【输出格式】
对于每组数据输出”Possible”或者”Impossible”.
【样例输入】
2
3 3 11
0 2 7
0 1 6
1 2 5
2 1 10000
1 0 1
【样例输出】
Possible
Impossible
【样例解释】
第一组:0 -> 1 -> 2 :11
第二组:显然偶数时间都是不可能的。
【数据范围】
30%: T <= 10000
另有30%: n <= 5 , m <= 10.
100%: 2 <= n <= 50 , 1 <= m <= 100 , 1 <= z <= 10000 , 1 <= T <= 10^18 , Case <= 5.
暴力dp30:
- /*
- 暴力dp 30
- 状态f[i][j]表示到了i号节点走了j的状态是否存在
- 可以水过T比较小的数据
- */
- #include<iostream>
- #include<cstdio>
- #include<cstring>
- #define maxn 1000010
- using namespace std;
- int T,t,n,m,f[][maxn],g[][];
- void Clear(){
- memset(f,,sizeof(f));
- memset(g,,sizeof(g));
- }
- int main()
- {
- freopen("travel.in","r",stdin);
- freopen("travel.out","w",stdout);
- scanf("%d",&T);
- while(T--){
- scanf("%d%d%d",&n,&m,&t);
- int u,v,s;Clear();
- for(int i=;i<=m;i++){
- scanf("%d%d%d",&u,&v,&s);
- u++;v++;
- g[u][v]=g[v][u]=s;
- }
- f[][]=;
- for(int j=;j<=t;j++)
- for(int i=;i<=n;i++)
- for(int k=;k<=n;k++){
- if(!g[i][k]||j-g[i][k]<)continue;
- f[i][j]=f[i][j]||f[k][j-g[i][k]];
- }
- if(f[n][t])printf("Possible\n");
- else printf("Impossible\n");
- }
- return ;
- }
正解SFPA:
- /*
- 正解是最短路~~~~
- 一开始以为图论 后来认为是dp 没想到最后又回到图论了~~
- 前面dp做法的瓶颈很显然是T太大~
- 但是出入的边的权值和要小的多 所以会在某个环了转圈
- 假设有一条路径走一遍的时间为t 中间有一个长度为p的环
- 那这条路可以认为是t+p*k长度的
- 所以我们只需要维护这个多出来的t就好了 先选一个环
- 保险起见 选从零出发的最小的环 长度设为x
- 定义dis[i][j] 表示到了i 时间为j+k*x 且k最小 这里跑最短路找最小
- 为什么找最小呢 因为只有当dis[n][T%x]<=T 时才可以 所以为了尽量满足条件
- 维护最小的dis
- */
- #include<iostream>
- #include<cstdio>
- #include<cstring>
- #include<queue>
- #define maxn 210
- #define ll long long
- using namespace std;
- ll T,t,n,m,num,head[maxn],dis[maxn][maxn*],mxx,f[maxn][maxn];
- struct node{
- ll v,t,pre;
- }e[maxn*];
- struct point{
- int v,s;
- };
- queue<point>q;
- void Clear(){
- memset(head,,sizeof(head));
- memset(f,,sizeof(f));
- num=;
- }
- ll min(ll a,ll b){
- return a<b?a:b;
- }
- void Add(ll from,ll to,ll dis){
- num++;e[num].v=to;
- e[num].t=dis;
- e[num].pre=head[from];
- head[from]=num;
- }
- void SPFA(){
- memset(dis,/,sizeof(dis));
- q.push((point){,});
- f[][]=;dis[][]=;
- while(!q.empty()){
- ll x=q.front().v;
- ll s=q.front().s;
- q.pop();f[x][s]=;
- for(int i=head[x];i;i=e[i].pre){
- ll v=e[i].v;
- ll di=s+e[i].t;
- di%=mxx;//这里分清谁做下标谁是dis值
- if(dis[v][di]>s+e[i].t){
- dis[v][di]=s+e[i].t;
- if(f[v][di]==){
- f[v][di]=;
- q.push((point){v,di});
- }
- }
- }
- }
- }
- int main()
- {
- freopen("travel.in","r",stdin);
- freopen("travel.out","w",stdout);
- cin>>T;
- while(T--){
- cin>>n>>m>>t;
- ll u,v,s;Clear();
- mxx=0x7fffffff;
- for(int i=;i<=m;i++){
- cin>>u>>v>>s;
- u++;v++;
- Add(u,v,s);Add(v,u,s);
- if(u==||v==)mxx=min(mxx,s);
- }
- if(mxx==0x7fffffff){//不连通
- printf("Impossible\n");
- continue;
- }
- mxx*=;
- SPFA();
- if(dis[n][t%mxx]<=t)printf("Possible\n");
- else printf("Impossible\n");
- }
- return ;
- }
9.5noip模拟试题的更多相关文章
- 模拟试题C
模拟试题C 一.单项选择题(2′*14 =28′) 1.双线性法向插值法(Phong Shading)的优点是( ) A)法向计算精确 B)高光域准确 C)对光源和视点没有限制 D)速度较快 2.用编 ...
- 模拟试题B
模拟试题B 一.单项选择题(2′*8 =16′) 1.灰度等级为256级,分辨率为2048*1024的显示器,至少需要的帧缓存容量为( ) A)512KB B)1MB C)2MB D)3MB 2.在多 ...
- 模拟试题A
模拟试题A 一.单项选择题(2′*12=24′) 1.下面各种坐标变换中,会产生变换前后维度的改变的是( ) A)建模变换 B)观察变换 C)投影变换 D)视口变换 2.下列描述深度缓冲消隐算法的特点 ...
- CCF 模拟试题——出现次数最多的数 官方答案解析及自己写的正确答案
前几天知道的CCF计算机职业资格认证考试,觉得好像比软考含金量高一些,就去了解了一下,做了模拟试题中的 “出现次数最多的数” 这道题,我的算法和官方答案算法不同,个人觉得觉得官方的好一点,没那么繁琐, ...
- 11.9 noip模拟试题
NOIP2016 模拟赛——那些年,我们学过的文化课背单词(word.c/cpp/pas)[题目描述]fqk 退役后开始补习文化课啦, 于是他打开了英语必修一开始背单词. 看着满篇的单词非常头疼, 而 ...
- 10.26 noip模拟试题
enc[问题背景]zhx 和他的妹子聊天.[问题描述]考虑一种简单的加密算法.假定所有句子都由小写英文字母构成,对于每一个字母,我们将它唯一地映射到另一个字母.例如考虑映射规则:a->b, b- ...
- 9.29noip模拟试题
环上的游戏(cycle) 有一个取数的游戏.初始时,给出一个环,环上的每条边上都有一个非负整数.这些整数中至少有一个0.然后,将一枚硬币放在环上的一个节点上.两个玩家就是以这个放硬币的节点为起点开始这 ...
- 9.20 noip模拟试题
Problem 1 双色球(ball.cpp/c/pas) [题目描述] 机房来了新一届的学弟学妹,邪恶的chenzeyu97发现一位学弟与他同名,于是他当起了善良的学长233 “来来来,学弟,我 ...
- 9.16noip模拟试题
题目描述 在幻想乡,东风谷早苗是以高达控闻名的高中生宅巫女.某一天,早苗终于入手了最新款的钢达姆模型.作为最新的钢达姆,当然有了与以往不同的功能了,那就是它能够自动行走,厉害吧(好吧,我自重).早苗的 ...
随机推荐
- bzoj2395: [Balkan 2011]Timeismoney
Description 有n个城市(编号从0..n-1),m条公路(双向的),从中选择n-1条边,使得任意的两个城市能够连通,一条边需要的c的费用和t的时间,定义一个方案的权值v=n-1条边 ...
- Linux——搭建PHP开发环境第四步:composer
原文链接:https://my.oschina.net/jiangbianwanghai/blog/473249 1.下载composer.phar [root#localhost opt]# cur ...
- Thinking In Java 学习笔记 1-5 章
第1章 对象导论 本章主要讲OOP的思想及一些OOP基本概念 1.抽象过程:万物都是对象,对象具有状态.行为和标识.对象拥有属性和方法,以及在内存中的唯一地址. 2.每个对象都有一个接口:通过接口给对 ...
- Extjs打开window窗口自动加载html网页
Window inherits the autoLoad config option from Panel. Note that I included all config options below ...
- Billboard
hdu2795:http://acm.hdu.edu.cn/showproblem.php?pid=2795 题意:给一个h*w的公告牌,h是高度,w是宽度,一个单位高度1为一行,然后会有一些公告贴上 ...
- Maven实战一
转载:http://www.iteye.com/topic/1123221 1. 用Maven 命令创建一个简单的Maven项目 在cmd中运行如下命令: Cmd代码 mvn archetype:ge ...
- c++ explicit
C++ explicit关键字用来修饰类的构造函数,表明该构造函数是显式的,既然有"显式"那么必然就有"隐式",那么什么是显示而什么又是隐式的呢? 如果c++类 ...
- 两款商业拓扑发现软件siteview和ElementSentry的比较
今天在公司试用了一下两款商业拓扑发现软件游龙科技的siteview和速方软件ElementSentry. 条目/产品 速方软件ElementSentryv5.0 游龙科技Siteview NNM v3 ...
- [OSX] 取消开机启动
以Pulse Secure为例 参考:https://kb.pulsesecure.net/articles/Pulse_Secure_Article/KB26679 输入指令: launchctl ...
- POJ3617 Best Cow Line
其实是学习参考了算法书的代码,但仍然是我自己写的,有小差别.贪心类型. #include <iostream> using namespace std; int main() { int ...