因为上次做TC,还是没有超过1200,所以下一场比赛还是要在div2做,所以还是训练div2.
level 1:这一题我们只要区别离我们最近的是在边上还是在棱角上。这样我们并区别开之后,我们就可以完成了。
level 2:因为我们有这样(n, 1), (n, -1), (-n, 1), (-n, -1), (1, n), (-1, n), (1, -n) or (-1, -n)八种选择,其实我们可以使用(n , 1),(1 , n) , (-1 , n) , (n , - 1)这样四种的多项式来表达,及
a * (n - 1) + b*(1 , n) + c * (-1 , n) + d*(n - 1) = (x , y)。在化解后,我们可以得到:
a = (n * k1 - k2 + x) / 2 ;
b = (-k2 - n * k1 - x) / 2;
c = (n * k2 - k1 + y ) / 2;
d = (-k1 - y - n * k2) / 2;
这样我们要保证a , b , c , d都是整数就可以了。我们还可以发现,只要能保证a是整数,也能保证b是整数。同样c和d也是一样的。所以我们只要保证a 和 c是整数就可以了。这样我们可以对n, x , y进行讨论,看看能否存在k1,k2是的我们的a和c是整数。当n时偶数时,不管x,y的奇偶性,都是可以的。当n是奇数时,当x和y的奇偶性相同时就可以了。这样要注意是他们绝对值的奇偶性相同就可以了。
level 3:计算在字符串[low ... high]之间的1的个数,我们只要分开算出字符串[0 .. high] 和 字符串[0 .. low - 1](注意当low是0的时候)差就可以了。因为str[n]的长度可能会很长,str[n] = str[n - 1] + str[n - 1 - k] + .....,因为high和low的长度是在long long 范围之内的,所以我们只要根据high和low来计算str[n]的前几项就可以了。附上代码:
const long long MAX = 1000000000000000000LL;
typedef long long LL;
LL len[150];
LL ones[150];
bool hash[150];
class MagicalGirlLevelThreeDivTwo
{
public:
int theCount(vector <string> first, int n, long long lo, long long hi)
{
memset(hash , 0 , sizeof(hash));
memset(len , -1 , sizeof(len));
memset(ones , -1 , sizeof(ones));
for (int i=0 ; i<first.size() ; i++) {
len[i] = first[i].length();
int oneCnt = 0;
for (int j=0 ; j<first[i].length() ; j++) {
if (first[i][j] == '1') {
oneCnt++;
}
}
ones[i] = oneCnt;
}
for (int i=first.size() ; i<=n ; i++) {
LL lenTemp = 0;
LL onesTemp = 0;
bool flag1 = true;
bool flag2 = true;
for (int j=i - 1 ; j>=0 ; j -= first.size()) {
if (flag1) {
if (len[j] != -1) {
lenTemp += len[j];
if (lenTemp >= MAX) {
flag1 = false;
}
}
else {
flag1 = false;
}
}
if (flag2)
{
if (ones[j] != -1) {
onesTemp += ones[j];
if (onesTemp >= MAX) {
flag2 = false;
}
}
else {
flag2 = false;
}
}
}
if (flag1) {
len[i] = lenTemp;
}
else {
len[i] = -1;
}
if (flag2) {
ones[i] = onesTemp;
}
else {
ones[i] = -1;
}
}
LL ret = getNum(n , hi , first) - getNum(n , lo - 1 , first);
return (int)ret;
}
LL getNum(int index , LL pos , vector<string>first)
{
LL ret = 0;
if (index < first.size()) {
for (int i=0 ; i<=pos ; i++) {
if (first[index][i] == '1')
ret++;
}
return ret;
}
LL temp = 0;
for (int i=index - 1 ; i>=0 ; i-=first.size()) {
if (check(i , first)) {
LL iLen = len[i];
if (temp + iLen - 1 >= pos) {
return ret + getNum(i , pos - temp , first);
}
else {
temp += iLen;
ret += ones[i];
}
}
else {
return ret += getNum(i , pos - temp , first);
}
}
}
bool check(int index , vector<string> first)
{
if (len[index] == -1) return false;
return true;
}
};