Pro3979 篮球 题解
×
dfs意义:从x过来的最小值
记忆化dfs定义f数组存储结果
//dfs函数
long long int dfs(int x,int lwalk,int rwalk)
{
if(f[x][lwalk][rwalk]!=0x7f7f7f7f7f7f7f7f) return f[x][lwalk][rwalk]提示!该题解未通过审核,建议分享者本着启发他人,照亮自己的初衷以图文并茂形式完善之,请勿粘贴代码。........................................................................ 该题解等待再次审核........................................................................(剩余 820 个中英字符)
题目3979 篮球
AAAAAAAAAAAAAAAAAAAA
2024-06-22 03:56:21
|
|
一个妙妙思路 将棋子按位置从小到大排序后一对一对看,如1 2 3 4,[1,2]为一对,[3,4]为一对 每对中左边的那个棋子如果往左移了几步,右边的棋子也移动相同的步数,对结果没有影响;但如果右边的棋子往左移,就会对结果有影响,右边的棋子最多移动到左边棋子的右边1格的位置 所以其实只需要维护每对石子之间的距离,类似Nim游戏,当每一对石子相差1时无法移动 如果给定的n为奇数,则多加入一个位置为0的点,与最小的那个为一对
题目2660 [POJ 1704]格鲁吉亚和鲍勃
A
4
评论
2024-06-07 16:01:06
|
|
Pro3979 篮球 题解
×
#include<bits/stdc++.h> using namespace std; 提示!该题解未通过审核,建议分享者本着启发他人,照亮自己的初衷以图文并茂形式完善之,请勿粘贴代码。........................................................................ 该题解等待再次审核........................................................................(剩余 947 个中英字符)
题目3979 篮球
2024-05-28 20:36:09
|
|
这不是一篇题解,只是偶然发现大多数提交的复杂度都是错的。 其实只是少了一个剪枝:对所有搜索得到的二元组 $(state,sum)$ 去重。 以下记 $N=2n$。 如果不去重,考虑一组数据满足 $a_i=1$。此时前一半中 $sum=i$ 的状态有 $[x^i](1+x+x^{-1})^n=[x^{i+n}](1+x+x^2)^n$ 个,记作 $f_i$。 由于我们是对于每一个后一半的状态,遍历所有前一半与之相等的状态,那么总遍历量为 $\sum_i{f_i^2}$。查一下 OEIS 发现,这个东西是 $O(\frac{3^{2n+0.5}}{2\sqrt{2\pi n}})$ 也就是 $O(\frac{3^{N+0.5}}{2\sqrt{\pi N}})$ 的,其实不比 $O(3^N)$ 的暴力优多少,证明在link。 然而如果去重了,一个粗略的上界是,对于后一半的 $3^n$ 个状态,前一半中最多有 $2^n$ 个状态与之对应,那么就是 $O(6^{\frac{N}{2}})$ 的。此时也能看出,某谷上一堆说复杂度是 $O(3^{\frac{N}{2}})$ 的题解全是瞎扯。 值得注意的是,官方其实还给出了一种 $(1+\sqrt{1.5})^N$ 的做法,奈何我英语不好看不懂。链接是link。
题目769 [USACO Open12] 平衡奶牛子集
8
评论
2024-05-26 17:28:36
|
|
发现最难受的是每行必须选最大值,不好统一刻画。 但是我们可以直接转化这个问题:泛化为从每行选一个数,求最大可能值。不难发现这样答案不会变化。 于是可以状压 dp,$f(i,S)$ 表示处理完前 $i$ 列,目前 $S$ 中为 $1$ 的行已经选上数的最大可能值。 转移直接枚举循环位移,然后枚举子集转移即可。$\mathcal O(Tmn3^n)$。 再做一些最优性的分析,加以预处理,可以做到 $\mathcal O(T(m\log m + n^32^n + n3^n))$。
题目3249 Rotate Columns
7
评论
2024-05-24 16:45:08
|
|
Pro1699 中位数 题解//阅读须知:请读完第六行后跳到主函数阅读,有利于理解程序。 //思路:建立一个最大为n/2+1的小根堆,将数据输入小根堆,若堆满就删除堆顶元素,直到数据全部输入。 //若n为偶数,则中位数为堆顶元素,否则中位数为堆顶元素与左孩子和右孩子间更小的那个元素的算数平均值,即(堆顶元素+左孩子与右孩子间更小的那个)/2 #include<iostream> #include<cstdio> using namespace std; int a[260000]; //定义小根堆a int n,s=0,b,t;//n:需处理数据数量,s:堆内元素数量,b:输入媒介(数据中转),t:未处理数据数量 void swim(int s)//上浮操作,变量s为需要进行上浮的数据,本函数用于插入 { while(s>1&&a[s]<a[s/2]) { swap(a[s],a[s/2]); s/=2; } } void push(int b)//插入数据 { a[++s]=b; swim(s); //此处s为要上浮的元素在堆中的下标,详见上浮函数swim } void jd()//建立小根堆a,此时a中包含了输入数据中前n/2+1个数据 { for(int i=1;i<=n/2+1;++i) { cin>>b; push(b); //将b插入至堆中,详见插入函数push } } void sink(int k)//下沉操作,k恒为1 { while(2*k<=n/2+1) { int j=2*k; if(j+1<=n/2+1&&a[j]>a[j+1]) { j=j+1; } if(a[k]<=a[j]) { break; } swap(a[k],a[j]); k=j; } } void pop()//删除数据 { a[1]=a[s--]; //将堆顶替换为堆底元素 sink(1); } int main() { freopen("median.in","r",stdin); freopen("median.out","w",stdout); cin>>n; jd(); //建堆,详见建堆函数jd t=n-(n/2+1); //计算未处理数据数量,以免在循环里计算导致超时 while(t) //当数据没有处理完时 { t--; //剩余数据-1 cin>>b; push(b); //将输入数据b插入堆中,详见插入函数push pop(); //将堆顶(下标最小的不可能为中位数的元素)删除,详见删除函数pop } if(n%2) //当n为奇数 { printf("%0.1f\n",1.0*a[1]); } else { printf("%0.1f\n",1.0*(a[1]+min(a[2],a[3]))/2.0); } return 0; } //Adam与GS53热心创作
题目1699 中位数
AAAAAAAAAAAAAAAAAAAA
8
评论
2024-05-14 21:32:50
|