USACO3.2题目简析
chunlvxiong的博客
T1:Factorials
题意:输出N!最后非零位(1≤N≤4220)。
首先你可以很快算出N!的末尾0的个数(即1到N的5的因子个数,记这个数为x)。然后你可以理解为求N!/(2^x)/(5^x) % 10的值。
这样你就可以以O(N)的时间复杂度计算出这个值。
T2:Stringsobits
题意:求出第i个长度为N(1≤N≤31)且这个二进制数中1的个数小于等于L(L<=N)的数(允许前导0)。
用dp[i][j]表示长度为i,1的个数≤j的数的个数,则dp[i][j]=dp[i-1][j-1](放1)+dp[i-1][j](放0)。初始:dp[0][i]=1
输出部分操作如下,从高位到低位操作,假设当前位数为x,还能放y个1,还需K个长度为N的且二进制数中1的个数小于等于L的数:
如果dp[x-1][y]>=K,那么说明这一位应该放0,然后继续操作x-1位。
如果dp[x-1][y]<K,那么说明这一位应该放1,然后K-=dp[x-1][y],然后y--(能放1的个数减少)。
这样逐位确定即可。注意K的最大值为2^32会超过int。时间复杂度O(N*L)。
T3:Spinning Wheels
题意:有5个水车,水车的角度为0..359,每个水车有一个速度,也有几个缺口。问最少多少s时,有一个角度所有水车都是缺口。若不存在这样的时刻,输出none。
首先答案肯定是<360的,因为第360时刻与第0时刻的结果是一样的。
那么你考虑如何验证一个时刻是否有一个角度所有水车是缺口,可以开一个标记数组进行统计,对于该时刻若某个角度当前水车是缺口,那么++,最后如果标技数组中有一个角度的值为5,说明该时刻有一个角度所有水车是缺口。
这样做的时间复杂度是O(360^2)的,可以A掉此题。注意不要忘记0时刻也是可能的情况。
T4:Feed Ratios
题意:有三种不同的混合饲料(每种配法都包含3种饲料),以及目标饲料,求如何将多少包这三种混合饲料混合可以得到多少包目标饲料。(每种混合饲料和目标饲料中3种饲料的数量均为<100的非负整数,同时保证每种混合饲料最多用100包)
爆搜即可,时间复杂度O(100^3)。注意0的情况。
T5:Magic Squares
题意:给出一个魔板,初始状态为1 2 3 4,记为{1,2,3,4,5,6,7,8}。有三种操作:“A”:交换上下两行;“B”:将最右边的一列插入最左边;“C”:魔板中央四格 8 7 6 5
给定一个目标状态,求初始状态到目标状态最少所需操作数以及相应的操作步骤(字典序最小)。
很容易想到广搜,总的状态数为8!种,并不多,因此广搜是可行的。关键问题在于如何判重。如果开一个8^8的标记数组,会MLE(得益于USACO的16M内存)。
判重实际上就是算一个序列是第几个全排列,以6 5 8 4 3 7 2 1为例进行分析:
第一个位置先前可以放1~5,所以先前已经有5*7!个全排列了。
第二个位置先前可以放1~4,所以先前已经有4*6!个全排列了。
第三个位置先前可以放1、2、3、4、7,所以先前已经有5*8!个全排列了。
……
所以判重计算方法为Σ(8-i)!*(a[i]-1-先前比a[i]小的数的个数)。--注:这里计算这个复杂度是O(8^2)的,不是很理想,可以利用线段树优化到O(8log8),但是还是不写的好。
另类判重方法:map判重,hash判重(找一个比8!大的素数)。
T5:Sweet Butter
题意:有N头奶牛(1≤N≤500),P个牧场(1≤P≤800),C条双向道路(1≤C≤1450)。给出每头奶牛所在的牧场编号,求出令所有奶牛聚到同一个牧场所有奶牛所走的距离总和的最小值。
由于是稀疏图,所以暴力穷举每个牧场作为集合牧场,然后跑spfa(或者堆优化的dijkstra)一遍,再计算出奶牛所走的距离总和,更新最小值即可。