本文只将我自己的解法公布,标准题解请等待官方正式题解报告
(暂无E题题解,欢迎补充)
Problem A Police and the Thief
博弈论 + 乱搞
首先我们定义Police和Thief之间的曼哈顿距离dis = |xp - xt| + |yp - yt|
作为一个聪明的小偷,他每次的行动会尽可能的使dis增大,而作为一个牛B的警察,他每次的行动会尽可能使dis减小
当然,由于小偷和警察的关系是小偷被警察追着跑
所以要使警察每次使dis-1并不难...
现在考虑小偷的面临的局面,若他在这个地图的非边界位置,他每次都可以使dis + 1,而警察会使dis - 1
若小偷在地图的边界位置上,小偷会遇到 不得不使dis - 1 ,而警察又会使dis - 1.
这样,dis - 2了
.......
在可预见的未来,我们知道,小偷和警察最后的位置应该只会有两种情况:
1.小偷和警察相邻;
2.小偷和警察对角相邻;(即在一个2*2的矩阵中,比如一个人在左上角,一个人在右下角,即为对角相邻)
现在我们考虑谁先手的问题。
若小偷先手,二者相邻的话,小偷是不会被抓住的;二者若对角相邻,反之。
同理可得警察先手的情况。
整体思路为上所述,但是还是要考虑一些特殊情况:1.二者一开始就在一起;2.地图的形状很特殊:n*1或1*m的
Problem B Similar strings
乱搞
对于长度不同的串我们暂且不讨论,一下讨论的为长度相同的串。
对于题目的意思,不妨定义为判断两个串的“模式”是否相同。
思路是将每个串都转换到一个数组里面,然后判断两个数组是否完全相同。
对于转换的方式,我们可以这样直接“离散化”(感觉差不多就这个意思)
Problem C The Game of Little P
贪心+数学+乱搞
为了得到最大的Score,我们容易得到这样的做法:能连Combo就连Combo,连不了就休息一回合再连下去,即我们说我们连“一套”Combo加一个休息为循环节
思路很简单,但是题目数据是很大的,几乎卡在了int的边界上面,所以求一套Combo的分数不能for了。
求一套Combo的分数可以在O(1)时间内完成。
接下来是处理 mod 运算的方式,易知:(A * B) mod C = ((A mod C) * (B mod C)) mod C
但是感觉对于公式中,除以常数6是个很讨厌的地方,因为他不尽满足上述等式的性质。
故在计算一套Combo的值的时候,需要将除以6单独带入分子的表达式中验证哪个表达式(或哪两个表达式)是可以被其整除的。
Problem DTrees
乱搞
对于输入的序列,我们先进行一边处理。
处理的方式是,我们首先假想有所有的Sequence都是基于以下模式的Sequence的:
1 2 3 4 …… 4 3 2 1
于是,我们不难想到,求出序列中,每棵树 对应上述Sequence 的 “距离”是多少(即达到这样的要求的差距)
这样,我们求出的每个“距离”,找出 拥有该距离最多的 树的数目 的即为应当保留不变的 树的数目
(其实抽象的来看,我们只是将斜面化成了平面就迎刃而解了)
下面附上代码:
Problem A
第一题代码有点瑕疵,其中注释前的部分是我比赛时提交通过的代码,注释后的是我比赛之后YY觉得应该改成那样的,主要看思路吧。
/*
* ID: Allen_3
* Prob: Police and the thief
* LANG: C++
*/
#include
#include
#include
using namespace std;
const char THIEF[6] = "thief";
int T , n , m;
int xp , yp , xt , yt;
char str[20];
int main()
{
scanf("%d" , &T);
for (int i = 0;i < T;i ++)
{
scanf("%d%d" , &n , &m);
scanf("%d%d%d%d" , &xp , &yp , &xt , &yt);
scanf("%s" , str);
int delta = abs(xp - xt) + abs(yp - yt);
if ((xp == xt) && (yp == yt))
{
printf("YES\n");
continue;
}
if (n == 1 || m == 1)
{
//if (delta % 2 == 0)
printf("YES\n");
/*
else
printf("NO\n");
*/
continue;
}
if (strcmp(str , THIEF) == 0)
{
if (delta % 2 == 0)
printf("YES\n");
else
printf("NO\n");
}
else
{
if (delta % 2 == 0)
printf("NO\n");
else
printf("YES\n");
}
} //for i _ T
return 0;
} //main
Problem B
/*
* ID: Allen_3
* Prob: Similar strings
* LANG: C++
*/
#include
#include
using namespace std;
int T;
int len_a , len_b;
char stra[100010] , strb[100010];
int arra[100010] , arrb[100010];
int hash[200];
int main()
{
scanf("%d" , &T);
for (int i = 0;i < T;i ++)
{
scanf("%s" , stra);
scanf("%s" , strb);
len_a = strlen(stra); len_b = strlen(strb);
if (len_a == len_b)
{
int tmpa = 0 , tmpb = 0;
memset(hash , -1 , sizeof(hash));
for (int i = 0;i < len_a;i ++)
{
if (hash[stra[i]] == -1)
hash[stra[i]] = tmpa ++;
arra[i] = hash[stra[i]];
}
memset(hash , -1 , sizeof(hash));
for (int i = 0;i < len_b;i ++)
{
if (hash[strb[i]] == -1)
hash[strb[i]] = tmpb ++;
arrb[i] = hash[strb[i]];
}
bool flag = true;
for (int i = 0;i < len_a;i ++)
if (arra[i] != arrb[i])
{
flag = false;
break;
}
if (flag)
printf("YES\n");
else
printf("NO\n");
} //len_a == len_b
else
printf("NO\n");
} //for i _ T
return 0;
} //main
/*
* ID: Allen_3
* Prob: The Game of Little P
* LANG: C++
*/
#include
#include
#include
using namespace std;
#define MOD 1000000007LL
#ifdef unix
#define LL_FMT "%lld"
#else
#define LL_FMT "%I64d"
#endif // unix
int T;
long long n , m;
void solve()
{
long long ans = 0 , tmp;
long long a = m * (m + 1) ;
long long b = 2 * m + 1;
bool flag1 = false , flag2 = false;
if (!flag1 && (a % 2 == 0))
{
flag1 = true;
a = a / 2;
}
if (!flag2 && (a % 3 == 0))
{
flag2 = true;
a = a / 3;
}
if (!flag1 && (b % 2 == 0))
{
flag1 = true;
b = b / 2;
}
if (!flag2 && (b % 3 == 0))
{
flag2 = true;
b = b / 3;
}
tmp = ((a % MOD) * (b % MOD)) % MOD;
long long ll = n / (m + 1) , mm;
ans = (tmp * ll) % MOD;
mm = n - ll * (m + 1);
a = mm * (mm + 1); b = 2 * mm + 1;
flag1 = false ; flag2 = false;
if (!flag1 && (a % 2 == 0))
{
flag1 = true;
a = a / 2;
}
if (!flag2 && (a % 3 == 0))
{
flag2 = true;
a = a / 3;
}
if (!flag1 && (b % 2 == 0))
{
flag1 = true;
b = b / 2;
}
if (!flag2 && (b % 3 == 0))
{
flag2 = true;
b = b / 3;
}
tmp = ((a % MOD) * (b % MOD)) % MOD;
ans = (ans + tmp) % MOD;
printf(LL_FMT"\n" , ans);
} //solve
int main()
{
scanf("%d" , &T);
for (int i = 0;i < T;i ++)
{
scanf(LL_FMT LL_FMT , &n , &m);
solve();
} //for i _ T
return 0;
} //main
/*
* ID: Allen_3
* Prob: Trees
* LANG: C++
*/
#include
#include
#include
using namespace std;
int T , n;
int arr[100010];
int hash[300010];
void solve()
{
memset(hash , 0 , sizeof(hash));
for (int i = 0;i < (n >> 1);i ++)
{
arr[i] -= i;
arr[n - i - 1] -= i;
} //for i _ n
if (n & 1)
arr[n >> 1] -= (n >> 1);
for (int i = 0;i < n;i ++)
{
if (arr[i] > 0)
hash[arr[i]] ++;
}
int ans = 0;
for (int i = 0;i < n;i ++)
{
if (arr[i] > 0 && hash[arr[i]] > ans)
ans = hash[arr[i]];
}
printf("%d\n" , n - ans);
} //solve
int main()
{
scanf("%d" , &T);
for (int i = 0;i < T;i ++)
{
scanf("%d" , &n);
for (int i = 0;i < n;i ++)
scanf("%d" , &arr[i]);
solve();
} //for i _ T
return 0;
} //main
暂无