「2019.7.18 考试」关于压力下的加速度。

今天早上又考了一场。

现在题还没改完,先写一下考试路程。

我习惯性的先看完了三道题。

然后昨天教练还读了一下那个IOI选手的答题思路,就是先切第三题然后攻T2,我的话打算先把T3打个暴力就不管他,跑到考试结束连个6也没跑出来于是结束了。

然后我就开始写T1的暴力了。

看出来是欧拉路,但是我不会统计,然而用map判重一个傻逼重载运算符我卡了半天写不对,最后还是用了随机化hash的思想rand出了几百个数,挨个和边经过次数乘起来作为hash值这样的,然后判重过了,这道题就弃了开始干T2。

T2我的思路真的是一点一点来的。

T2是这次比较成功的一部分,虽然分数不是很理想(卡常不到位),我和天皇的暴力基本一样,但是他加了个clock然后70了。

说一下暴力的思路,我的期望得分是(80),但是这个数据稍微有点苟,大于1e5的数据全都是1e9的,导致我全都MLE。

1.首先狗掉了k==1和k==0的思路,k==0的话就直接GCD即可,k==1也同样是GCD,只需要枚举不同的集合GCD,然后判断不包含的那个是不是剪掉之后小于1,之后选出来最大的一个GCD即可。

2.在观察数据范围,1e5范围的值域其实可以暴力切掉,1e5*100暴力判断即可,到这里是40。

3.在接着qj不了数据范围了。

但是我找到了一个性质:如果一个数d不符合要求,那么他的倍数也不符合要求,这样我们就可以打个埃筛,筛掉很多后面的数。

复杂度变成了一个loglogn的,虽然还要判断,不过只需要判断质数也就是ln(n)的大小,虽然还是要循环O(n),但是判断只需要判断质数是否成立即可,因为前面的全部被他的最小质因子筛掉了,线筛会更优秀一些,基本接近线性了,所以我估分到了80,虽然是50,但是收获还是蛮大的。

正解是数论分块,学反演的时候学过一次,同样和筛是一起学的,不过我对筛的认识还是比分快清晰一些,这样考场上打了筛而不是分块。

 

好了现在可以写一下题解了。

 

第一题的话,基本没怎么想正解,不过欧拉路那个的确想到了,没接着想,打了个暴力就过了,这个决定挺正确的,因为我后来看了正解之后,也想了好久才写了30分。

首先可以把每条边全都分为正反向两条边,这样每个点的度数都是偶数了,这些有向边的话随便去除两条就可以达到效果,即其中两条是只走一次。

那么剩下来的那些边必然也要保证是一条欧拉回路,也就是说,删的边有所要求,符合要求方案就是ans。

三种情况:任意两个自环被删掉,任意自环和一条普通边被删掉(从普通边出发即可),两条有共同端点的边(保证奇点个数为偶)。

这样计算一次出答案,特判掉虫洞不联通的情况。

 

第二题,暴力的思路基本被我挖干净了,直接正解就行了。

数论分块的一个小板子,推一下式子吧。

$ \sum \limits_{i=1}^n (\left \lceil \frac{a_i}{d} \right \rceil d-a_i) \leq k $

$ d \sum \limits_{i=1}^n \left \lceil \frac{a_i}{d} \right \rceil \leq k+\sum \limits_{i=1}^n a_i $

$ \sum \limits_{i=1}^n \left \lceil \frac{a_i}{d} \right \rceil \leqslant \left \lfloor \frac{k+ \sum \limits_{i=1}^n a_i }{d} \right \rfloor $

发现右边是个数论分块的裸板子,可以$ O(\sqrt{n}) $处理。

那么来证明一下数论分块的正确性(之前听学长讲反演的时候听过),但是一直没有试着自己证明一下来的。

现在来试一试。

结论是:满足 $ \frac{n}{last} = \frac{n}{i} $ 的最大的last的值是 $ \left \lfloor \frac{n}{\left \lfloor \frac{n}{i} \right \rfloor } \right \rfloor $

那么证明:

$ last=i+d $

$ ki+p=n $

$ k(i+d) + p'= n $

$ p' = p-kd $

$ d_{max} = \left \lfloor \frac{(p-p')}{k} \right \rfloor = \left \lfloor \frac{p}{k} \right \rfloor $

$ last = i+d =i+ \left \lfloor \frac{p}{k} \right \rfloor $

$ last = i+d =i+ \left \lfloor \frac{n- \left \lfloor \frac{n}{i} \right \rfloor i }{ \left \lfloor \frac{n}{i} \right \rfloor } \right \rfloor $

$ last = i+d = \left \lfloor i+ \frac{n- \left \lfloor \frac{n}{i} \right \rfloor i }{ \left \lfloor \frac{n}{i} \right \rfloor } \right \rfloor $

$ last = i+d = \left \lfloor \frac{n}{ \left \lfloor \frac{n}{i} \right \rfloor } \right \rfloor $

得证了。

那么这题可以分块根号n解决了。

还有一个优化。

我们思考一下d的上界,如果d减去最小的 $ a_i $ 大于k,显然不成立,那么分块上界可以缩小到了 $ d_{min}=a_{min}+k $这样这题基本挖光了。

 

下面是第三题,一个神仙dp。

dp本身没什么说的,神就是神,思路也神,设的也神,sdfz的神犇全都打了正解也神。

虽然本身神的我无话可说但是还是有一些可以吸收的营养。

另num=dp[i-1][l]*dp[i-1][r]

分情况:

1.什么都不做:dp[i][l+r]+=num

2.新根作一条:dp[i][l+r+1]+=num

3.根和两边的连成一条:dp[i][l+r-1]+=2*num*l*r

4.根和两边的某一条连:dp[i][l+r]+=2*num*(l+r)

5.根和两边(同一侧)的两条连起来:dp[i][l+r-1]+=num*(l*(l-1)+r*(r-1))

下面说一下我的理解。

首先dp是一种设计。你需要用你的决策方程来维护你设计的dp状态,使得终阶段的答案状态是正确,满足要求的。

那么看一下这五个方程分别满足了原题的什么性质。

1.满足继承性,我的子树里所拥有的方案我也要拥有。

2.满足扩展性,新来的根要扩展出。

3.满足融合性,我们考虑把新根融入上一阶段的状态和决策中。

4.满足有序性,我正着反着连到同一条边上,是不同的方案。

5.满足新增性,也就是说多了我这一个点,上一阶段的某一些状态也会在这一阶段作出改变。

满足这些性质,这个dp虽然神的要死。

但终归是令人惊叹但正确无误的。

 

关于题目的加速度。

前几天的时候刷题的速度有点快,我自己也感觉到不太对劲了。但是我觉得对面那个D队的做题实在太快了,我不敢松懈,我觉得在自家OJ让人虐让人打脸我很不爽,我真不爽。

然后就刻意提高速度,说实话这个过程很难受,感觉就是强行加速一样,那几天身体状况都不太好了起来,我觉得可能我那时候多半心态有一些问题。刻意提速是有问题的,当时可能是很受打击之类反正有一种情绪在里面,情绪这个东西控制不好就会炸。当时实在是心急了,现在想想教练说的挺对的,自己不要被别人的速度所干扰,不要因为别人比你强就是强行追赶他,这样下去你的速度被干扰了,最后肯定会垮掉,如果真的你用自己的速度到最后赶不上他那就认了就行了,因为你尽了全力还是不如他,就承认不如他就可以了,这也没什么丢人的。说的挺有道理的。

压力这个是必须要有的,但是加速度必须是恒定的,也就是说你的进步速度必须是恒定的,不被外界干扰,不被情绪干扰,可以有情绪,但不能被他干扰,这很重要,这样会进步,而且会很快很稳。

不要贪大贪多,能力多少就一次吃多少,不图快,图稳,扎实,这样后期一定会进步飞快。

什么不行就要练什么,现在对于那个第一机房还是第二机房我觉得应该淡然一点,如果你的考试能力足够了,就去学知识,如果不够的话,那么就去考试就行了,两方面都很重要,教练分给你的一定是当前最适合你的一种训练方式。

sdfz那边的确很强,这会让很多人有压力,学长那届也比我们强,但是最后我们不一定就会差。

竞赛这个东西,毕竟不学到最后,是不会知道结果的。

 

那今天就这么多。

 

//T1
#include<iostream>
#include<cstdio>
using namespace std; typedef long long ll; const int maxn=1e5+5; int n,m,x,y,tot,cnt,first[maxn],vis[maxn],d[maxn]; ll ans,sum; struct Road{ int u,t,nxt; }eage[maxn<<1]; void add(int x,int y) { eage[++tot].u=x; eage[tot].t=y; eage[tot].nxt=first[x]; first[x]=tot; } void dfs(int x) { vis[x]=1; for(int i=first[x];i;i=eage[i].nxt,cnt++) if(vis[eage[i].t]==0) dfs(eage[i].t); } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=m;i++) { scanf("%d%d",&x,&y); add(x,y);add(y,x); if(x==y) sum++; if(x!=y) d[x]++,d[y]++; } for(int i=1;i<=n;i++) if(d[i]) { dfs(i); break; } if(cnt<m*2) { puts("0"); return 0; } for(int i=1;i<=n;i++) ans+=1LL*d[i]*(d[i]-1)/2; ans+=1LL*(m-sum)*sum; ans+=1LL*sum*(sum-1)/2; printf("%lld\n",ans); return 0; }

 

//T2
#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std; typedef long long ll; const int maxn=105; ll ans,res,sum,n,k,a[maxn]; int main() { scanf("%lld%lld",&n,&k); for(int i=1;i<=n;i++) { scanf("%lld",&a[i]); sum+=a[i]; } sum+=k; for(ll i=1,pre;i<=sum;i=pre+1) { pre=sum/(sum/i);res=0; for(int j=1;j<=n;j++) { ll d=(a[j]-1)/pre+1; res+=pre*d; } if(res<=sum) ans=pre; } printf("%lld\n",ans); return 0; }
 
  
//T3
#include<iostream> #include<cstdio> using namespace std; typedef long long ll; const int maxn=305; ll ans,n,m,dp[maxn][maxn]; int main() { scanf("%lld%lld",&n,&m); dp[1][0]=dp[1][1]=1; const int mod=m; for(register int i=1;i<=n-1;++i) { int t=(i>=20?n-i+1:min((ll)(1<<i)-1,n-i+1)); for(register int l=0;l<=t;++l) for(register int r=0;r<=t&&l+r-1<=n-i+1;++r) { ll sum=dp[i][l]*dp[i][r]%mod; dp[i+1][l+r]=(dp[i+1][l+r]+sum)%mod; dp[i+1][l+r+1]=(dp[i+1][l+r+1]+sum)%mod; dp[i+

转载于:https://www.cnblogs.com/Lrefrain/p/11206408.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值