因为一个疏忽改了好久,写的很冗长,反正过了就不管了,题目本身不难
由于运算满足结合律,所以 长度为 L*X
的运算 的结果一定要等于 i*j*k = -1
小数据的话从头走,记录 head[i] 表示 s[0] * s[1] * ... * s[i]
同理 tail[i] = s[L*X-1-i] * ... * s[L*X-1]
目标就是找到 head[l] = 'i',tail[r] = 'k' (l < L*X-1-r)
显然如果存在 l, r 的话,那就一定有解 (因为 [l, r] 中间的结果一定是 ‘j’)
O(n) 遍历 newL = L*X
就行了
接下来研究大数据
假设 S = s[0] * s[1] * ... * s[L-1]
显然有 l = S^k + l2 (k<X, l2<L)
,因为可以观察到 S^k
是有周期性的
可以优化一下 0<=k<min(X, 4)
这时候 newL = min(X, 4)*L
把小数据的代码改一下就行了
#include <iostream>
#include <string>
using namespace std;
const int maxn = 40010;
typedef long long ll;
int T;
ll L, X;
string s;
//i=2, j=3, k=4
int mat[5][5] = {
{0, 0, 0, 0, 0},
{0, 1, 2, 3, 4},
{0, 2, -1, 4, -3},
{0, 3, -4, -1, 2},
{0, 4, 3, -2, -1}
};
int chartoijk(char x)
{
return x-'i'+2;
}
int a[maxn];
int head[maxn];
int tail[maxn];
int main()
{
// freopen("a.in", "r", stdin);
// freopen("b2.out", "w", stdout);
cin>>T;
for (int kase = 1; kase <= T; kase++)
{
cin>>L>>X;
cin>>s;
printf("Case #%d: ", kase);
//长度不够
if (L*X < 3)
{
puts("NO");
continue;
}
for (int i = 0; i < L; ++i)
a[i] = chartoijk(s[i]);
for (int i = 1; i < min(X, (ll)4); ++i)
for (int j = 0; j < L; ++j)
a[i*L + j] = a[j];
ll newL = L*min(X, (ll)4);
int p = head[0] = a[0], q, tmp;
for (int i = 1; i < newL; ++i)
{
q = a[i];
tmp = mat[abs(p)][q];
if (p < 0) tmp = -tmp;
p = tmp;
head[i] = p;
}
if (head[X%4*L-1] != -1)
{
puts("NO");
continue;
}
p = tail[0] = a[newL-1];
for (int i = 1; i < newL; ++i)
{
q = a[newL-1-i];
tmp = mat[q][abs(p)];
if (p < 0) tmp = -tmp;
p = tmp;
tail[i] = p;
}
int l=0, r=0;
bool ans = false;
while(l < (L*X-1-r))
{
if (head[l] != 2)
{
l++;
continue;
}
while( l<(L*X-1-r) && r<newL && tail[r]!=4)
r++;
if (l<(L*X-1-r) && r<newL)
{
ans = true;
break;
}
}
printf("%s\n", ans ? "YES" : "NO");
}
return 0;
}