T1 木板
求\sqrt{n}~n间有多少个数的平方是n的倍数
通过打表可以发现(我没带脑子我看不出来),符合条件的数构成一个等差数列,公差为首项
而首项就是将n质因数分解后每个质因数出现次数除二,向上取整,这个数一定是大于\sqrt{n}的最小的符合条件的数
\sqrt{n}将n分解质因数后求出首项,(n-1)/首项就是小于n里有几个,即答案
积累:papa大神教我,打表之前先猜规律,用小点看看猜的对不对,然后再用大点验证,想不出来的数学题就打打表,找找规律
T2 打扫卫生
首先肯定是dp
考场写的是n^2的,每次用桶把a[j]的贡献减去,更新答案,最后再循环一遍都加回来,T60
但我们发现如果不同的数的个数大于了\sqrt{n},那么他一定不优(大于\sqrt{n},那还不如一段就一个,这样就只有n)
所以我们可以在往回加的时候特判,如果cnt大于\sqrt{n},那就记录下这个位置,然后break,下次循环就只从pos循环就行了,加上这个减枝可以到T80
正解:cnt一定小于\sqrt{n},那么我们枚举i前不同的数的个数,复杂度就降到了O(n\sqrt{n})
用pre[a[i]]记录a[i]上次出现的位置,b[j]表示从b[j]+1~i一共有j个不同的数,c[j]表示从b[j]+1~i有多少个不同的数
i++后,如果pre[a[i]]<=j,说明a[i]在b[j]+1~i-1这一段没有出现过,所以b[j]+1~i这一段中不同数的个数就变成了c[j]+1,更新c[j],同时更新f[i]数组
如果c[j]>j,我们为了维护c[j]==j,就需要调整b[j]的位置,使b[j]合法
设pos=b[j]+1(原位置),如果pre[a[pos]]>pos说明在后面还有一个a[pos],那么删掉这个对个数没有影响,直到pre[a[pos]]<=pos,那么删掉这个数,pos+1~i这个区间就正好有j个数了,更新b[j]=pos,c[j]=j
原文地址:https://www.cnblogs.com/jrf123/p/11664119.html