洛谷9月noip模拟赛
2015-09-22 23:39
453 查看
第一题:
求一个排列是第几小(字典序)用康托展开。
例如 求3214的字典序。
我们从高位开始比较,比3小的有两位,即2*3!=12,再比较下一位2,比2小的只有1,且1没有用过,所以再加1*2!=2,再比较1,没有比1小的数,最后一位因为比它小的树必定已经全部被用过,所以不需要比较。
故3214的字典序为12+2+1=14.
所以对于这道题,我们先预算出1~10的阶乘,然后再康托展开即可。
贴代码:
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> using namespace std; int n,ans,num; string s; int a[11]; bool vis[11]; int main() { scanf("%d",&n); cin>>s; a[0]=1; for(int i=1;i<=10;i++) a[i]=a[i-1]*i; memset(vis,true,sizeof(vis)); ans=1; for(int i=0;i<n;i++) { int k=s[i]-'0'; vis[k]=false; num=0; for(int j=1;j<k;j++) if(vis[j]==true)num++; ans+=num*a[n-i-1]; } cout<<ans<<endl; }
第二题:
求树上任意两点之间所有边权的异或。设a,b两点的最近公共祖先为c,题目即为求a~c~b的异或,可以知道x^y^y=x,故只需求a,b到树根的异或的异或,从树根到c的边权异或两次后相当于未运算。
贴代码:
#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> using namespace std; struct Node{ int to,val,next; }e[200005]; int head[100005]; bool vis[100005]; int xo[100005]; int tot=0; void add(int u,int v,int w) { e[++tot].to=v; e[tot].val=w; e[tot].next=head[u]; head[u]=tot; } void dfs(int u) { vis[u]=true; for(int i=head[u];i!=0;i=e[i].next) if(!vis[e[i].to]) { int v=e[i].to; xo[v]=xo[u]^e[i].val; dfs(v); } } int main() { int u,v,w,n,m; scanf("%d",&n); memset(head,0,sizeof(head)); for(int i=1;i<n;i++) { scanf("%d%d%d",&u,&v,&w); add(u,v,w); add(v,u,w); } xo[u]=0; dfs(1); scanf("%d",&m); for(int i=1;i<=m;i++) { scanf("%d%d",&u,&v); printf("%d\n",xo[u]^xo[v]); } return 0; }
第三题:
题目链接:http://www.luogu.org/problem/show?pid=2583这次考试唯一有价值的题目。
看完题目后,第一感觉是动规,然而自己想了想状态转移方程并没有想出来——>捂脸(其实是状态选择的不太对,造成转移困难)。
于是就去问学长了,学长说是最短路,(i,j)表示第i时刻在第j站,如果原地等待就在(i,j)到(i+1,j)建边
然而接受了学长的教导后,我并没有做出来23333
Golve最后提供了动规的思路%%%
Dp[i][j]表示i时刻,在第j站到达n最少还需等待多长时间。
初始化:dp[t]
=0;
Dp[t][1~n-1]=INF.
我们还需要一个数组hastrain[i][j][0]表示i时刻j车站有一辆从左到右的火车;
Hastrain[i][j][1]表示i时刻j车站有一辆从右到左的火车。
Hastrain可以在读入时就处理好。
对于题目中的每个点,我们一定是从后更新前,因为最后的状态是确定的(初始化),所以每个点会有三种情况。
1.原地等待 dp[i][j]=dp[i+1][j]+1;
2.从左开向右
满足条件 j< n,hastrain[i][j][0]==true,i+ti[j]<=t
Dp[i][j]=min(dp[i][j],dp[i+ti[j]][j+1]);
3.从右向左开
满足条件j>1,hastrain[i][j][1]==true,i+ti[j-1]<=t
Dp[i][j]=min(dp[i][j],dp[i+ti[j-1]][j-1]);
输出按照格式就可以AC啦。
贴代码:
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> using namespace std; int n,t,m,INF; int ti[60]; bool hastrain[300][60][3]; int dp[300][53]; int main() { int ca=0; while(scanf("%d",&n)&&n!=0) { ca++; scanf("%d",&t); INF=t; ti[0]=0; for(int i=1;i<n;i++) scanf("%d",&ti[i]),INF-=ti[i]; INF+=5; memset(hastrain,false,sizeof(hastrain)); int x; scanf("%d",&m); for(int i=1;i<=m;i++) { scanf("%d",&x); hastrain[x][1][0]=true; int num=x; for(int j=1;j<=n;j++) { num+=ti[j]; if(num>t)break; hastrain[num][j+1][0]=true; } } scanf("%d",&m); for(int i=1;i<=m;i++) { scanf("%d",&x); hastrain[x] [1]=true; int num=x; for(int j=n-1;j>=1;j--) { num+=ti[j]; if(num>t)break; hastrain[num][j][1]=true; } } for(int i=1;i<=n-1;i++)dp[t][i]=INF; dp[t] =0; for(int i=t-1;i>=0;i--) for(int j=1;j<=n;j++) { dp[i][j]=dp[i+1][j]+1; if(j<n&&hastrain[i][j][0]&&i+ti[j]<=t) dp[i][j]=min(dp[i][j],dp[i+ti[j]][j+1]); if(j>1&&hastrain[i][j][1]&&i+ti[j-1]<=t) dp[i][j]=min(dp[i][j],dp[i+ti[j-1]][j-1]); } cout<<"Case Number "<<ca<<": "; if(dp[0][1]>=INF)cout<<"impossible\n"; else cout<<dp[0][1]<<"\n"; } return 0; }
总结:前两道题都是一次通过的,然后最后一道过了5~6遍,得了85.74。
让我们总结一下为什么错这么多遍吧。(错误不分先后,记忆废)
(1)貌似一开始INF设错了,最大应该是总时间t减去通往每个站的时间,但我一开始设为了一个大整数。
(2)然后提交后还是错误,我心想不可能吧,是不是服务器出错了,然后什么都没改又交了一遍(真是傻到无可救药了)
(3)好吧真正错这么多遍的原因是 输!出!格!式!
空格出没的那么诡异真的好吗,好吧,以后做题要把样例复制粘贴观察格式
—————————全剧终——————————————————-
相关文章推荐
- Servlet事件监听器
- c/c++语言数据类型转换的方式及常见问题【绝笔整理】
- 黑马程序员----C 语言学习笔记之程序的结构及分类
- ubuntu 环境下编译 hadoop 2.6.0的简单方法
- PHP基础------抽象类------接口
- csdn 使用live writer
- Linux系统资源使用情况
- Python之列表推导式
- 一起学CC3200之OTA固件升级(使用HTTP方式下载APP:初级篇)
- 2015北京网络赛 G题 Boxes bfs
- redis的有序集合在score相同的情况 下是如何排序的
- 2.精通前端系列技术之seajs模块化使工作更简单(二)
- Oracle EBS提交请求遇到“无管理器”错误
- 【随便做做|线段树】POJ3667 Hotel
- 并查集求集合的个数
- HDU - 2639 Bone Collector II(第K大01背包)
- git and eclipse
- Hadoop2.6+jdk8的安装部署(1)——使用jar包安装部署【详细】
- Spring MVC
- 个人博客作业Week3