TC SRM 514 DIV2

第一次用新号做SRM~首先,咳咳,很高兴能跟方方同学一起做SRM~

这次总共做了3个,但只交上了两个,1000pt的那个想到算法了,代码也写完了,不过test时发现有两组数据出问题,于是debug。。。时间不够啦。。只能赛后补上啦,rating到了1433~

250pt是个简单的几何题,不需要啥技巧,仅仅需要判断点是否在正方形的   里面/上下边界内的右边/上下边界内的左边/左右边界内的上边/左右边界内的下边/其他,然后针对每种情况返回一个值就可以了。

500pt是个判定性问题,判断n-knight jump是否能从点(0, 0)到点(x,y)。由于数据量比较小,偶直接用裸bfs水过去了。没想到那题是有规律的- -!很多人的代码比偶的bfs短多了(当时偶还纳闷怎么可能有人480+pt过呢,打字也太快了吧~)。偶开了个200*200的数组模拟地图,方方直接用60*60的就过啦,orz~果真女神牛~

1000pt乍一看是个字符串问题,仔细一看是个数学题。大致解法是:首先预处理一下l[i]和f[i]表示A[i]的长度和1的总个数,由于l[i]可能会很大,实践证明会超过long long的上限,所以当l[i]超过hi直接将其赋值为hi+2就可以了。然后写一个方法Cal(pos)计算A[n]的前pos位有多少个1,那么结果就是Cal(hi)-Cal(lo-1)。注意我们使用Cal是很难直接计算出结果的,需要逐步逼近结果,就像组合中的区间计数问题一样,贴上后来Pass ST的代码,每个测试点用时均不超过2ms。

View Code
//1000pt Pass ST Code

#include
<iostream>
#include
<cstdio>
#include
<cstring>
#include
<string>
#include
<vector>
using namespace std;

typedef
long long llg;

class MagicalGirlLevelThreeDivTwo
{
public:
llg sum, l[
110], f[110];
int k;

llg Cal(vector
<string> &first, int n, llg pos)
{
int i, ans;
llg sum;
if(pos < 0) return 0;
if(n < k)
{
ans
= 0;
for(i = 0; i <= pos; i++)
if(first[n][i] == '1') ans++;
return ans;
}
else
{
i
= n-1;
ans
= 0;
sum
= -1;
while(i >= 0)
{
if(sum+l[i] >= pos)
return ans+Cal(first, i, pos-sum-1);
else
{
sum
+= l[i];
ans
+= f[i];
}
i
-= k;
}
}
}

int theCount(vector <string> first, int n, long long lo, long long hi)
{
int i, j, len;
k
= first.size();
for(i = 0; i < k; i++)
{
f[i]
= 0;
len
= first[i].length();
l[i]
= len;
for(j = 0; j < len; j++)
if(first[i][j] == '1')
f[i]
++;
}
i
= k;
while(i <= n)
{
f[i]
= l[i] = 0;
j
= i-1;
while(j >= 0)
{
f[i]
+= f[j];
l[i]
= min(hi+2, l[j]+l[i]);
j
-= k;
}
i
++;
}
//for(i = 0; i <= n; i++) cout<<f[i]<<" ";
//cout<<endl;
return Cal(first, n, hi) - Cal(first, n, lo-1);
}
};

1000pt还有一种解法,看别人代码发现的:由于hi-lo<=100,所以可以针对每一位单独判断累加就可以了,这种解法可能写起来比我的那个要简单一点,直观一点。不过偶的可以过掉更大的数据~哈哈~

the last but not least, 加油哈!

posted on 2011-08-10 15:27  Moon_1st  阅读(255)  评论(0编辑  收藏  举报

导航