西北工业大学省赛选拔!!!
2017-04-30 03:14
288 查看
这次打的超级不好
1.直接上手E题结果那个输入的最后一个是5 1OOOOOOO/9999999 其中是O 而不是0
然后本来可以一血的,结果卡了好久也没过
2 ABC暴力题刚开始没认真读题然后就姿势不对,一直到自己明白题意才过
3 F题当时没几个人过感觉会很难,没做其实是签到题!!!
4 做题太慢导致D题没有好好思考,也就没好好做
A https://vjudge.net/problem/UVALive-7091
B https://vjudge.net/problem/UVALive-7092
C https://vjudge.net/problem/UVALive-7094
D https://vjudge.net/problem/UVALive-7095
E https://vjudge.net/problem/UVALive-7096
F https://vjudge.net/problem/UVALive-7097
A:
读入数据初始化vis数组,push优先队列(权值大的优先)
从大到小站队,用vis数组记录这个还在不在,然后top的下标的后面的人数加起来就是这个人站队需要的次数!
最后 vis清零该节点 pop,输出ans就行了。
#include <iostream>
#include<algorithm>
#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std;
int num[25];
bool vis[25];
struct node
{
int data;
int ord;
bool friend operator < (const struct node a,const struct node b)
{
return a.data<b.data;
}
};
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
priority_queue<node> que;
int cnt;
struct node u;
scanf("%d",&cnt);
for(int i=1;i<=20;i++)
{
scanf("%d",&u.data);
u.ord=i;
que.push(u);
num[i]=i;
vis[i]=1;
}
int ans=0;
while(!que.empty())
{
u=que.top(); que.pop();
for(int i=u.ord+1;i<=20;i++)
{
ans+=vis[i];
}
vis[u.ord]=0;
}
printf("%d %d\n",cnt,ans);
}
return 0;
}
B:问有几个区间,其中包含的数都大于 左-1和右+1 的值
题意:
暴力枚举起点和终点,模拟即可
#include <iostream>
#include<algorithm>
#include<stdio.h>
#include<string.h>
using namespace std;
int num[16];
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int cnt;
scanf("%d",&cnt);
for(int i=1;i<=12;i++)
{
scanf("%d",&num[i]);
}
int ans=0;
for(int i=2;i<=11;i++)
{
for(int j=i;j<=11;j++)
{
bool ssc=1;
for(int k=i;k<=j;k++)
{
if(num[k]<=num[i-1]||num[k]<=num[j+1]) { ssc=0; break;}
}
if(ssc) ans++;
}
}
printf("%d %d\n",cnt,ans);
}
return 0;
}
C:题意判断是否是happ+质数(happy各个位的数值的平方之和 递归如果出现1 则 是happy num)
{
1.素数用素数筛,微大于O(n)的复杂度
2.当时懒得想判断是否有循环,直接循环100次如果没有出现过happy就说明不是happy
}
#include <iostream>
#include<algorithm>
#include<stdio.h>
#include<string.h>
using namespace std;
const int maxn=1e5+100;
bool pim[maxn];
void get()
{
memset(pim,1,sizeof(pim));
pim[1]=0;
for(int i=2;i<maxn;i++)
{
if(pim[i])
{
for(int j=2*i;j<maxn;j+=i)
{
pim[j]=0;
}
}
}
}
int getnum(int num)
{
int x=num;
int ans=0;
while(x)
{
int flag=x%10;
ans+=(flag*flag);
x/=10;
}
return ans;
}
bool dfs(int pos,int step)
{
if(step>=100) return 0;
if(pos==1) return 1;
return dfs(getnum(pos),step+1);
}
int main()
{
int T;
scanf("%d",&T);
get();
while(T--)
{
int cnt,num;
scanf("%d %d",&cnt,&num);
if(pim[num]&&dfs(num,0))
{
printf("%d %d YES\n",cnt,num);
}
else
{
printf("%d %d NO\n",cnt,num);
}
}
return 0;
}
D
个人感觉D题是最难的一道题,当时没来得及做
插入当时侍聚聚手推过程。我也是赛后看他的代码才明白是什么规律。
预处理答案即可
{
1.将i-1的长度和值全部都塞给i;
2.扫一遍{
->1. 如果是大于0的数 ,--即可
->2.如果第j个位置是0的话,改成j ,结束循环
}
3.如果每个数值都大于0,将len[i]++;然后 ans[k][len[i]]=len[i];
4.输出每十个换一次行,为了这个pe了一发
}
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int ans[2010][85];
int len[2010];
int main ()
{
memset(ans,0,sizeof(ans));
memset(len,0,sizeof(len));
len[0]=1;
for(int i=1;i<=2000;i++)
{
len[i]=len[i-1];
for(int j=1;j<=len[i];j++)
{
ans[i][j]=ans[i-1][j];
}
for(int j=1;j<=len[i];j++)
{
if(ans[i][j])
{
ans[i][j]--;
}
else
{
ans[i][j]=j;break;
}
}
if(ans[i][len[i]]==len[i]-1) { len[i]++; ans[i][len[i]]=len[i] ;}
}
int t;
scanf("%d",&t);
while(t--)
{
int cnt,k;
scanf("%d%d",&cnt,&k);
printf("%d %d\n",cnt,len[k]);
int tt=0;
for(int i=1;i<=len[k];i++)
{
++tt;
printf("%d",ans[k][i]);
if(tt==10)
{
printf("\n");tt=0;
}
else if(i!=len[k]) printf(" ");
}
if(len[k]%10) printf("\n");
}
return 0;
}
E题真是血崩。
题意 父亲节点为p/q ,左儿子 p/(p+q) 右儿子 (p+q)/q; 给一点求它的下一个点
做法
{
讨论即可
1.当 q==1 的时候 输出 1/p+1;
2.当p<q 的时候 输出 q/q-p;
3. 当p>q 递归向上until p<q(同时记录递归了多少层)再求记录层数的左子树即可
}
#include <iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
void work(int cnt,long long p,long long q)
{
if(q==1)
{
printf("%d %lld/%lld\n",cnt,q,p+1);
return;
}
else if(p<q)
{
printf("%d %lld/%lld\n",cnt,q,q-p);
return;
}
else
{
long long pp=p,qq=q;
long long step=0;
while(1)
{
if(pp<qq) break;
pp=pp-qq;
step++;
}
long long x,y;
x=pp; y=qq;
pp=y;
qq=y-x;
while(1)
{
if(step==0) break;
pp=pp;
qq=pp+qq;
step--;
}
printf("%d %lld/%lld\n",cnt,pp,qq);
}
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int cnt;
long long p=0,q=0;
scanf("%d %d/%d",&cnt,&p,&q);
work(cnt,p,q);
}
return 0;
}
//5 1/1OOOOOOO
F 其实是个大水题。后悔啊。
只有正号 讨论x,y的大小就可以了。
x<y 2步 否则6步即可;
#include <iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
int ax[25];
int ay[25];
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int tt,x,y;
scanf("%d%d%d",&tt,&x,&y);
if(x<y)
{
printf("%d %d %d %d\n",tt,2,x,y);
}
else
{
if(x+2<=x-y+5) printf("%d NO PATH\n",tt);
else printf("%d %d %d %d %d %d %d %d\n",tt,6,1,2,3,x-y+5,x+2,x+3);
}
}
return 0;
}
1.直接上手E题结果那个输入的最后一个是5 1OOOOOOO/9999999 其中是O 而不是0
然后本来可以一血的,结果卡了好久也没过
2 ABC暴力题刚开始没认真读题然后就姿势不对,一直到自己明白题意才过
3 F题当时没几个人过感觉会很难,没做其实是签到题!!!
4 做题太慢导致D题没有好好思考,也就没好好做
A https://vjudge.net/problem/UVALive-7091
B https://vjudge.net/problem/UVALive-7092
C https://vjudge.net/problem/UVALive-7094
D https://vjudge.net/problem/UVALive-7095
E https://vjudge.net/problem/UVALive-7096
F https://vjudge.net/problem/UVALive-7097
A:
读入数据初始化vis数组,push优先队列(权值大的优先)
从大到小站队,用vis数组记录这个还在不在,然后top的下标的后面的人数加起来就是这个人站队需要的次数!
最后 vis清零该节点 pop,输出ans就行了。
#include <iostream>
#include<algorithm>
#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std;
int num[25];
bool vis[25];
struct node
{
int data;
int ord;
bool friend operator < (const struct node a,const struct node b)
{
return a.data<b.data;
}
};
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
priority_queue<node> que;
int cnt;
struct node u;
scanf("%d",&cnt);
for(int i=1;i<=20;i++)
{
scanf("%d",&u.data);
u.ord=i;
que.push(u);
num[i]=i;
vis[i]=1;
}
int ans=0;
while(!que.empty())
{
u=que.top(); que.pop();
for(int i=u.ord+1;i<=20;i++)
{
ans+=vis[i];
}
vis[u.ord]=0;
}
printf("%d %d\n",cnt,ans);
}
return 0;
}
B:问有几个区间,其中包含的数都大于 左-1和右+1 的值
题意:
暴力枚举起点和终点,模拟即可
#include <iostream>
#include<algorithm>
#include<stdio.h>
#include<string.h>
using namespace std;
int num[16];
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int cnt;
scanf("%d",&cnt);
for(int i=1;i<=12;i++)
{
scanf("%d",&num[i]);
}
int ans=0;
for(int i=2;i<=11;i++)
{
for(int j=i;j<=11;j++)
{
bool ssc=1;
for(int k=i;k<=j;k++)
{
if(num[k]<=num[i-1]||num[k]<=num[j+1]) { ssc=0; break;}
}
if(ssc) ans++;
}
}
printf("%d %d\n",cnt,ans);
}
return 0;
}
C:题意判断是否是happ+质数(happy各个位的数值的平方之和 递归如果出现1 则 是happy num)
{
1.素数用素数筛,微大于O(n)的复杂度
2.当时懒得想判断是否有循环,直接循环100次如果没有出现过happy就说明不是happy
}
#include <iostream>
#include<algorithm>
#include<stdio.h>
#include<string.h>
using namespace std;
const int maxn=1e5+100;
bool pim[maxn];
void get()
{
memset(pim,1,sizeof(pim));
pim[1]=0;
for(int i=2;i<maxn;i++)
{
if(pim[i])
{
for(int j=2*i;j<maxn;j+=i)
{
pim[j]=0;
}
}
}
}
int getnum(int num)
{
int x=num;
int ans=0;
while(x)
{
int flag=x%10;
ans+=(flag*flag);
x/=10;
}
return ans;
}
bool dfs(int pos,int step)
{
if(step>=100) return 0;
if(pos==1) return 1;
return dfs(getnum(pos),step+1);
}
int main()
{
int T;
scanf("%d",&T);
get();
while(T--)
{
int cnt,num;
scanf("%d %d",&cnt,&num);
if(pim[num]&&dfs(num,0))
{
printf("%d %d YES\n",cnt,num);
}
else
{
printf("%d %d NO\n",cnt,num);
}
}
return 0;
}
D
个人感觉D题是最难的一道题,当时没来得及做
插入当时侍聚聚手推过程。我也是赛后看他的代码才明白是什么规律。
预处理答案即可
{
1.将i-1的长度和值全部都塞给i;
2.扫一遍{
->1. 如果是大于0的数 ,--即可
->2.如果第j个位置是0的话,改成j ,结束循环
}
3.如果每个数值都大于0,将len[i]++;然后 ans[k][len[i]]=len[i];
4.输出每十个换一次行,为了这个pe了一发
}
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int ans[2010][85];
int len[2010];
int main ()
{
memset(ans,0,sizeof(ans));
memset(len,0,sizeof(len));
len[0]=1;
for(int i=1;i<=2000;i++)
{
len[i]=len[i-1];
for(int j=1;j<=len[i];j++)
{
ans[i][j]=ans[i-1][j];
}
for(int j=1;j<=len[i];j++)
{
if(ans[i][j])
{
ans[i][j]--;
}
else
{
ans[i][j]=j;break;
}
}
if(ans[i][len[i]]==len[i]-1) { len[i]++; ans[i][len[i]]=len[i] ;}
}
int t;
scanf("%d",&t);
while(t--)
{
int cnt,k;
scanf("%d%d",&cnt,&k);
printf("%d %d\n",cnt,len[k]);
int tt=0;
for(int i=1;i<=len[k];i++)
{
++tt;
printf("%d",ans[k][i]);
if(tt==10)
{
printf("\n");tt=0;
}
else if(i!=len[k]) printf(" ");
}
if(len[k]%10) printf("\n");
}
return 0;
}
E题真是血崩。
题意 父亲节点为p/q ,左儿子 p/(p+q) 右儿子 (p+q)/q; 给一点求它的下一个点
做法
{
讨论即可
1.当 q==1 的时候 输出 1/p+1;
2.当p<q 的时候 输出 q/q-p;
3. 当p>q 递归向上until p<q(同时记录递归了多少层)再求记录层数的左子树即可
}
#include <iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
void work(int cnt,long long p,long long q)
{
if(q==1)
{
printf("%d %lld/%lld\n",cnt,q,p+1);
return;
}
else if(p<q)
{
printf("%d %lld/%lld\n",cnt,q,q-p);
return;
}
else
{
long long pp=p,qq=q;
long long step=0;
while(1)
{
if(pp<qq) break;
pp=pp-qq;
step++;
}
long long x,y;
x=pp; y=qq;
pp=y;
qq=y-x;
while(1)
{
if(step==0) break;
pp=pp;
qq=pp+qq;
step--;
}
printf("%d %lld/%lld\n",cnt,pp,qq);
}
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int cnt;
long long p=0,q=0;
scanf("%d %d/%d",&cnt,&p,&q);
work(cnt,p,q);
}
return 0;
}
//5 1/1OOOOOOO
F 其实是个大水题。后悔啊。
只有正号 讨论x,y的大小就可以了。
x<y 2步 否则6步即可;
#include <iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
int ax[25];
int ay[25];
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int tt,x,y;
scanf("%d%d%d",&tt,&x,&y);
if(x<y)
{
printf("%d %d %d %d\n",tt,2,x,y);
}
else
{
if(x+2<=x-y+5) printf("%d NO PATH\n",tt);
else printf("%d %d %d %d %d %d %d %d\n",tt,6,1,2,3,x-y+5,x+2,x+3);
}
}
return 0;
}
相关文章推荐
- 20160423/24省赛选拔总结
- 省赛选拔之愚人节专题
- acm省赛选拔组队赛经验谈
- 省赛选拔之愚人节专题
- SDU省赛选拔-ACM ICPC 2010–2011, NEERC, Northern Subregional Contest
- acm省赛选拔组队赛经验谈
- NYNU_省赛选拔题(3)
- QUST第七届省赛选拔-盗墓空间
- 2013省赛选拔
- NYNU_省赛选拔题(5)
- 2015省赛选拔
- NYNU_省赛选拔题(6)
- NYNU_省赛选拔题(7)
- XDU-2017省赛选拔第一场
- HNU 省赛选拔热身赛City Merger解题报告
- NYNU_省赛选拔题(8)
- 2014年省赛选拔组队系列赛2
- NYNU_省赛选拔题(10)
- 省赛选拔
- 省赛选拔第二场