| ||||||||||
| Online Judge | Problem Set | Authors | Online Contests | User | ||||||
|---|---|---|---|---|---|---|---|---|---|---|
| Web Board Home Page F.A.Qs Statistical Charts | Current Contest Past Contests Scheduled Contests Award Contest | |||||||||
解题报告In Reply To:7thSCUPC Posted by:windy7926778 at 2008-09-17 15:00:35 SCU-A Young tableau
直接搜索如果减枝的好的话是有可能过的
另外一种比较好的方法是
把所有合法的Young tableau都求出来
然后假设源矩阵变为特定的Young tableau
计算步数,这可以用置换群的相关知识来做
SCU-B Calculator
BFS就行了,注意不需要等号的情况
SCU-C Free square
先二分答案
现在判断<=mid共有多少个数是能被大于1的完全平方数整除
这个最大平方数最大可能是sqrt(mid)*sqrt(mid)
i从2枚举到sqrt(mid),计算有多少个数能被i*i整除
计数中会出现很多重复,如何去除重复成为关键
一种方法是,如果i已经能被大于1的完全平方数整除,那么不计它
否则统计它是多少个质数的乘积,根据容斥原理
如果为奇数个,则加上它,偶数个,减去它
SCU-D Distinct
两种方法
一种是求得中位数后用二分求得上界和下界 O(n*log2(m)) //m为数的大小
一种是用代数方法求得上界和下界 O(n)
SCU-E Rain and Fgj
很简单的网络流
首先把点拆成两个点,两点之间的边的权值为原来点的权值
原来的边的权值为无限大
显然最小割就是所求
SCU-F Remove
贪心,遇到任何一个位置,从0到9(首位从1开始)试探该位置的最小值
这可能需要用到当前位置的右边的最近的某个数字的位置
这可以用动态规划解决
[100000][10]
[i][j]记录当前位置为i,数字为j的右边的最近位置
[i][j]=[i+1][j];//如果当前位置的数不为j
[i][j]=i;//如果当前位置的数为j
可能还有更好的算法
SCU-G Honoi*3
定义:把三个相同的k看成X(k);
定义:A(k)完成上面X(K)不用保持相同之间的顺序的情况下最少步数。显然A(1)=3,A(2)=9........
定义:B(k)完成上面X(k)并且保持相同之间的顺序的情况下最少步数。显然B(1)=5,B(2)=17.......
如果在第k块的下面的所有都已经移好了,那把第X(K)的三块放好显然我们是从第二的跟移到第三的跟在这种情况下我们移动前面A(K)四次。明显可以得到公式B(k)=A(k-1)+A(k-1)+6+B(k-1)
A(K)的公式显然A(K)=A(K-1)+A(K-1)+3;
从上面的两个公式递推得到B(n)=6*2^n-7
SCU-H Common area
可以用半平面交来解决
注意多边形有可能是凹的,有可能完全重合,有可能一个被另外一个完全包括
SCU-I Match*3
用a[i][j]表示第1个字符串和第2个字符串当前位置分别为i和j的最大匹配数
用b[i][j]表示第1个字符串和第3个字符串
这是经典的DP问题,O(n^2)
对于每个i,求出a[i][j]的最大值,求出b[i][j]的最大值,两个最大值的最小值就为i的最大值,所有i的最大值的最大值就为答案
SCU-J Counting numbers
状态压缩DP
设数组f[1<<16][16]:f[i][j]中的状态i为二进制数,表示16个数位的某个集合,即当前状态使用过的那些数位,f[i][j]表示由这个集合的元素排列产生的数中对m取余得j的数的个数.
则f[i][j]=sum{ f[i-(1<<k)][t],且(t*10+a[k])%m==j },其中a[i]表示第i个数位上的数
SCU-K Perfect subsequece
两个观察
1.欲求子序列中必定没有两个相同的数
2.设子序列为a[i],a[i+1]...a[i+k-1],则此序列为Perfect subsequence的充要条件是它们中没有重复的数且它们的和为k*(k+1)/2
所以,我们先求出对于i的左右最近的会出现重复(不一定是自身重复)的下标,左为l[i],右为r[i],O(n)的复杂度
然后对于每个a[i]=1,分别向左和向右扫描,
以向左扫描为例,代码如下:
lmax=l[i];rmin=r[i];k=1;
for (j=i;j>=0;j--)
{
if (j<=lmax) break; // 若a[j]与以扫描数有相同,停止
if (lmax<l[j]) lmax=l[j];
if (rmin>r[j]) rmin=r[j]; // 更新左右边界
if (a[j]>k) k=a[j]; // 更新当前子序列的最大值
if (j+k-1>=rmin) continue;// 子序列的长度为k,设子序列以j为左边界,查看右边界是否越界.
if (j==0) s=sum[j+k-1];
else s=sum[j+k-1]-sum[j-1];
if (s==k*(k+1)/2 && k>ans) ans=k; // 查看子序列是否perfect
}
有i,j两重循环,似乎是n^2的复杂度
但考虑任意a[p],它最多只可能被左右离它最近的a[q]=1各扫描过一次,所以复杂度是O(n)
故总的复杂度是O(n)
Followed by:
Post your reply here: |
All Rights Reserved 2003-2013 Ying Fuchen,Xu Pengcheng,Xie Di
Any problem, Please Contact Administrator