2017-11-5离线赛总结(NOIP七连测第三场)
来源:互联网 发布:网络图标不见了 编辑:程序博客网 时间:2024/05/16 14:27
失分小结:
估分:100+80+40=220
实际分数:100+10+35=145
和估分相差甚远,主要是由于第一题的难度提升
又在第一题上卡了太久,导致第二题随便打了个暴力后又去水第三题
虽然主体顺序是没有错的,但是心态就不一样了,想着多水点分,又感觉时间来不及,虽然最后第二题想到了最小生成树,但又因为取边取错爆炸,暴力(dp)写错
题解:
Task 1:
第一题如果直接考虑两个数之间的关系的话,还是较为容易的,方案一共就只有
tip:当无法方案数很多时,可以把方案拆开,对单独的一个小步骤进行分析,然后利用排列组合求解
Task 2:
第二题也较为玄学,直接使用最小生成树算法可以卡过去
dp的大体转移好想,但具体的实现就较为困难
可以推出一个点有几种连接方案:
1.与自己这一列的前一个点相连
2.与自己这一列的后一个点相连
3.与自己对面一列的一个点相连
对于第三种情况,可以贪心地实现
可以推算出若其他点已经相连,那么若要把这个点加入,
就要选择离自己最近的点,然这里又有一个特殊情况:
在我们对面的右边的点实际上并没有被加入到点集里,所以连接离自己最近的右边的点可能才是最优的(在最小生成树的算法中,就是要把这两个离自己最近的点加进去)
然后先不考虑空间优化,可以发现自己在对面的转移实际只有两种情况
而在自己这一列的转移只有一种情况,所以递推式就很容易出来了
代码实现:
#include<bits/stdc++.h>using namespace std;#define M 1000005#define du doubleint A[M],B[M];du dp[2][2][2];int x3,x1,x2;du dist(int x,int y){ return sqrt((long long)(A[x]-B[y])*(A[x]-B[y])+x3);}int main(){ int n,m; scanf("%d%d%d%d",&n,&m,&x1,&x2); x3=1ll*(x1-x2)*(x1-x2); for(int i=1;i<=n;i++)scanf("%d",&A[i]),A[i]+=A[i-1]; for(int i=1;i<=m;i++)scanf("%d",&B[i]),B[i]+=B[i-1]; int j=1; dp[1][1][1]=dist(1,1); for(int i=1;i<=n;i++){// 1 i与j连通 0 i与j不连通 if(i>1){ dp[i&1][j&1][1]=min(dp[!(i&1)][j&1][1]+dist(i,j), min(dp[!(i&1)][j&1][1]+A[i]-A[i-1],dp[!(i&1)][j&1][0]+A[i]-A[i-1]+dist(i,j))); dp[i&1][j&1][0]=min(dp[!(i&1)][j&1][1],dp[!(i&1)][j&1][0]+A[i]-A[i-1]); } while(j<m&&(A[i]>=B[j]||i==n)){min(dp[i&1][!(j&1)][1]+B[j]-B[j-1],dp[i&1][!(j&1)][0]+B[j]-B[j-1]+dist(i,j))); dp[i&1][j&1][0]=min(dp[i&1][!(j&1)][1],dp[i&1][!(j&1)][0]+B[j]-B[j-1]); } } printf("%.2f\n",dp[n&1][m&1][1]); return 0;}
Task 3:
感觉这次的第三题相比于第二题的正解来说更好搞一些
第三题就是dfs加玄学剪枝
如果切了m=1这一档就可以清楚地发现这个方案数是可以根据组合数递推的
这题给出的诡异的切分也很玄妙,前面五十分n小一些,后面50分m小一些
前50分可以直接状压,后50分就直接枚举m的位置,然后用组合数算就好了
代码实现(只有后50分)
#include<bits/stdc++.h>using namespace std;#define FOR(i,x,y) for(int i=(x);i<=(y);i++)#define ll long longint n,m,P;struct node{ int id,pos; bool operator <(const node &s)const{return id<s.id;}}D[10];int C[35][35],fac[35];void init(){ FOR(i,0,30){cout<<666<<endl; C[i][0]=C[i][i]=1; FOR(j,1,i-1)C[i][j]=(C[i-1][j]+C[i-1][j-1])%P; } fac[0]=1; FOR(i,1,30)fac[i]=1ll*fac[i-1]*i%P;}bool mark[35],used[35];int ans;void dfs(int x,int res,int tmp){ res+=D[x].pos-D[x-1].pos; if(x>m){ tmp=1ll*tmp*fac[res]%P; ans=(ans+tmp)%P; return; } int sum=0; for(int i=1;i<=n;i++)used[i]=mark[i]; for(int i=D[x].pos;i<=n;i++)if(!mark[i]){ sum++; if(sum>res)break; dfs(x+1,res-sum,tmp*fac[sum]%P*C[sum][res]%P); mark[i]=1; } for(int i=1;i<=n;i++)mark[i]=used[i];}int main(){ init(); scanf("%d%d%d",&n,&m,&P); FOR(i,1,m)scanf("%d%d",&D[i].id,&D[i].pos); sort(D+1,D+1+m); D[m+1].pos=n; dfs(1,0,1); printf("%d\n",ans); return 0;}
- 2017-11-5离线赛总结(NOIP七连测第三场)
- 2017-11-8离线赛总结 (NOIP七连测第六场)
- 2017-11-4离线赛总结(NOIP七连测第二场)
- 2017-11-6离线赛总结(NOIP七连测第四场)
- 2017-11-7离线赛总结(NOIP七连测第五场)
- 2017-11-9离线赛总结 (NOIP七连测第七场)
- NOIP前3场模拟赛总结
- 第三场训练赛总结
- 2017-11-5离线赛总结
- #个人赛第三场解题总结#
- 2017暑假第二阶段第三场 总结
- CPC23第三场、第四场总结
- 2017-11-3离线赛总结
- 2017-11-3离线赛总结
- 2017-11-4离线赛总结
- 2017-11-6离线赛总结
- 2017-11-7离线赛总结
- 2017-11-8离线赛总结
- 第一章 第二课 什么是Scratch?
- Android当中的MVP模式(一)基本概念
- JAVA反射机制(转)
- 如何做一个对账系统
- 欢迎使用CSDN-markdown编辑器
- 2017-11-5离线赛总结(NOIP七连测第三场)
- 同余定理
- xml教程
- poj 2065 SETI(高斯消元)
- EXT的初步搭建
- SpringSeed 一个令人惊奇的Linux替代
- Retofit + RxJava 请求数据
- Android 当中的 MVP 模式(二)封装
- 一台电脑同时运行多个jdk