20170820考试总结
来源:互联网 发布:天刀捏脸数据女听风 编辑:程序博客网 时间:2024/06/05 17:24
第一题:树 tree
题目描述:已知一棵有根树,树的形态未知,已知树的最大深度为D,深度为i的节点有Ci个,i∈[1,D],求在所有可能的树中直径最长的树直径为多少。D<=10^5
题解:因为树的直径中一定包含一个深度最大的点,枚举其他深度的点,与深度最大的点构成直径,直径长度为它们两点的深度之和减去,在这两个点之前最深的一个Ci=1的点的深度(它们的lca),注意需要枚举到0(根的深度为0)。
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int N=100000+10;int ans,d,num[N],cut[N];int main(){ freopen("tree.in","r",stdin); freopen("tree.out","w",stdout); scanf("%d",&d); int bac=0; for(int i=1;i<=d;i++){ scanf("%d",&num[i]); if(num[i]==1) bac=i; cut[i]=bac; } for(int i=0;i<=d;i++){ int res=d+i-(cut[i]<<1); ans=max(ans,res); } printf("%d\n",ans);}
分数:85
分析:忘了考虑根的情况,本来构造了这样的数据,然而当时对深度的定义有点迷。。°(°ˊДˋ°) °。
第二题:酷子集 cool
题目描述:给出n,求一个1-n的集合有多少非空子集满足0-9所有数字出现次数不超过1。e.g:{12,345,67890}和{47,109}是cool子集,{147,342}不是。
题解: dp[S](S是一个10位二进制数,第i位为1表示i以出现过)表示0-9的状态为S时所有合法方案数,cnt[S]表示1-n中单独一个数0-9的状态为S的数有多少个,那么把S拆成两部分a,b(a&b=S)dp[S]=∑dp[a]*cnt[b],但这样是可能计算重复的,那么我们枚举时人为规定b必须包含lowbit(S)就可以避免重复。先dfs求出cnt,然后dp就可以了。(๑•́ ₃ •̀๑)
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<cmath>#include<vector>using namespace std;const int N=(1<<10)+10;const int mod=1e9+7;int n,ans,p,End,dp[N],cnt[N];inline void add(int&a,int b){ a+=b;if(a>mod)a-=mod;}int lowbit(int x){ return x&(-x);}void init(int x,int statu,int now){ if(now>0&&now<=n) cnt[statu]++; for(int i=0;i<=9;i++){ if(!now&&!i) continue ; if(1ll*now*10+i>n) break ; if(!(statu>>i&1)) init(x+1,statu|(1<<i),now*10+i); }}int main(){ freopen("cool.in","r",stdin); freopen("cool.out","w",stdout); scanf("%d",&n); End=(1<<10)-1; p=log10(n),init(0,0,0); dp[0]=1; for(int now=2;now<=End;now++){ int must=lowbit(now); for(int i=now;i>0;i=(i-1)&now) if(i&must){ int a=now-i; if(!a||!i) continue ; add(dp[now],dp[a]*cnt[i]); } add(dp[now],cnt[now]); add(ans,dp[now]); } printf("%d\n",ans);}
成绩:0
分析:考试时其实想到了正解的一部分,但是一直在纠结怎么判重O__O”…,完全没考虑枚举上的限制,然后就gg了/(ㄒoㄒ)/~~,考完后一听到lowbit感觉世界都明亮了(手动笑哭)
第三题:涂色方案 paint
题目描述:一个2*M的表格,要将其中r个涂成红色,g个涂成绿色,b个涂成蓝色,任意相邻的两个格子颜色不同,每种颜色在每个2 * 2的矩阵里至少出现一次,求方案数,对1e9+7取模。r+g+b=2 * m。m<=10^6
题解:先根据限制和观察,以一列的两个格子为一个单位,rg的旁边必须为br或gb(上下颠倒问题最后*2即可),那么问题变成了,给长度为m的一排格子涂三种颜色,相邻两个格子颜色不同的情况数为多少。看起来很想“湫秋系列故事——安排座位”,然而如果真的使用那道题的做法时间复杂度是O(n^3),显然会T (๑>m<๑) ,换一种考虑,这道题区别于“湫秋系列故事——安排座位”的地方在于它一定只有三种颜色( ⊙o⊙ )(a=rg,b=br,c=gb),那么我们假设先确定了a的位置每两个a之间会有一些空位,一共n-a个,考虑首尾是否为a,间隙个数有a,a-1,a+1三种情况,每两个空位之间的位置个数分为奇,偶两种情况,为偶数时只有bcbc…bc或cbcb…cb两种填法,而奇数的情况为bcb…bcb或cbc…cbc,设共n个位置,cnt个间隙,枚举其中i个间隙的长度为偶数,那么长度为奇数的间隙个数为cnt-i,现在i个偶数间隙中各放入一对b,c(bc,cb两种方法),构成C(pcnt,i) *2^i种情况,再在每个奇数间隙中放入一个b或者c,那么这两不放完之后,还剩下part=((n-i*2)-(cnt-i))/2-i对bc插入前面的间隙构成(相同的小球放入不同的盒子里,盒子可以为空),构成C(part+cnt-1,cnt-1)种情况,全部放完后b还剩下b-part-i个单独的b(c同理)然后这些单独的b和c就放入之前奇数间隙(前面把奇数补成偶数的时候就用这些b和c)构成C(cnt-i,b-part-i)种情况,最后把这三个数乘起来就为当前答案。首为a尾不为a或首不为a尾为a的情况一样,a个间隙的情况算两次,最后答案上下翻转也要*2.
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<cmath>using namespace std;const int mod=1e9+7;const int N=1000000+10;int m,r,g,b,fac[N],inv[N];inline void add(int&a,int b){ a+=b;if(a>=mod)a-=mod;}int qpow(int tmp,int p){ int res=1; while(p){ if(p&1)res=1ll*res*tmp%mod; tmp=1ll*tmp*tmp%mod,p>>=1; } return res;}int C(int n,int m){ return 1ll*fac[n]*inv[m]%mod*inv[n-m]%mod;}int calc(int cnt,int n,int g,int b){ if(cnt>n||cnt<1) return 0; int res=0; for(int i=0;i<=cnt&&i*2<=n;i++){ int least=n-i*2,type=cnt-i; //剩下的还有least个空余的位置,type个奇数长度的段 if((least-type)&1) continue ; else if(least<type) continue ; int part=(least-type)>>1;//剩下的一共还有part个组(B,C) int G=g-part-i,B=b-part-i;//剩下的B,C还有G,B个单独的 if(G<0||B<0||G+B!=type) continue ; int tmp=1ll*C(cnt,i)*qpow(2,i)%mod *C(part+cnt-1,cnt-1)%mod*C(type,G)%mod; add(res,tmp); } return res;}int main(){ freopen("paint.in","r",stdin); freopen("paint.out","w",stdout); scanf("%d",&m); scanf("%d %d %d",&r,&g,&b); r=m-r,g=m-g,b=m-b; if(r<0||g<0||b<0) printf("0\n"),exit(0); fac[0]=fac[1]=inv[0]=inv[1]=1; for(int i=2;i<=m;i++){ fac[i]=1ll*fac[i-1]*i%mod; inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod; } for(int i=2;i<=m;i++) inv[i]=1ll*inv[i-1]*inv[i]%mod; if(r);else if(g)swap(r,g);if(b) swap(r,b); int ans=0; add(ans,calc(r-1,m-r,g,b)); add(ans,calc(r+1,m-r,g,b)); add(ans,2ll*calc(r,m-r,g,b)%mod); (ans*=2)%=mod; printf("%d\n",ans);}
成绩:0
分析:第二题卡了太久,以至于完全没有时间仔细思考,直到最后才发现用“湫秋系列故事——安排座位”可以骗30分 o(╯□╰)o 2333但是这样的题确实没有见到过类似的(๑´ω`๑),最后那一段感觉特别绕o(@@)o,0分也算正常发挥%><%。
总结:第三题确实很难,然而第一题和第二题都很可惜QnQ,最近几场考试都在考思维(然而全部炸飞Konjak~),而且连续两次第二题卡太久,第三题没有时间(虽然这次第三题很难,但昨天的又水得良心(๑´ω`๑)2333333)。
- 20170820考试总结
- 考试总结
- 考试总结
- 考试总结
- 考试总结
- 考试总结
- 考试总结
- 考试总结
- 考试总结
- 考试总结
- 考试总结
- 考试总结
- 考试总结
- 考试总结
- 考试总结
- 考试总结
- 考试总结
- 考试总结
- poj 1091 跳蚤(容斥原理)
- 剑指offer_二叉树---从上往下打印二叉树
- hdu 4344 Mark the Rope (质因子分解+米勒拉宾素性)
- 基于内存的posix信号量用法
- 应聘高校教师的试讲技巧
- 20170820考试总结
- React Native组件(四)TextInput组件解析
- 无法访问Eclipse启动的Tomcat容器中的项目
- Java的加密技术(BASE64与单向加密算法MD5,SHA,MAC)
- 关于近期爬虫学习的总结
- python:基于wxpy微信聊天机器人
- getByClass
- Neo4j CQL
- STL总结——vector