题目的意思是,只有chalk的数量是奇数的Baker,才有机会成为winner,而且,成为winner的Baker才有机会按照自己的 favorite baker list,改变其他人的chalk的数量。
可以把开始的状态,看成是一个行向量, 且向量中的元素不是0就是1,因为题目只与奇偶性相关。
则在第1次celebration后,会有 B1 = B1 * A + B1 = B1 * (A + I),其中,A为转移矩阵,I为单位阵。
则根据 Fn+1 = Fn * (A + I) = F1 * (A + I)n的通项公式,以及二分矩阵幂的算法,可以求解。
#include <iostream>
#include <string.h>
using namespace std;
const int N = 102;
const int NAME_LENGTH = 22;
int X, n;
__int64 t;
char BakerName[N][NAME_LENGTH];
char TempName[NAME_LENGTH];
int WritePointer;
int i, j, k;
int ChalkNum, FriendList;
int BeginState[N];
int Transform[N][N];
int result[N][N];
int temp[N][N];
int EndState[N];
int find(const char *name)
{
int i = 1;
while(i != WritePointer)
{
if(!strcmp(name, BakerName[i]))
{
return i;
}
++i;
}
strcpy(BakerName[WritePointer++], name);
return (WritePointer - 1);
}
void init()
{
memset(BeginState, 0, sizeof(BeginState));
memset(Transform, 0, sizeof(Transform));
memset(EndState, 0, sizeof(EndState));
memset(BakerName, 0, sizeof(BakerName));
WritePointer = 1;
scanf("%d %I64d", &n, &t);
while(n--)
{
scanf("%s", TempName);
int i = find(TempName);
scanf("%d %d", &ChalkNum, &FriendList);
BeginState[i] = ChalkNum & 1;
while(FriendList--)
{
scanf("%s", TempName);
j = find(TempName);
Transform[i][j] = 1;
}
}
//转移矩阵B = A + I
for(i = 1; i <= WritePointer - 1; ++i)
{
Transform[i][i] += 1;
Transform[i][i] &= 1;
}
return;
}
void run()
{
int n = WritePointer - 1;
memset(result, 0, sizeof(result));
for(i = 1; i <=n; ++i )
{
result[i][i] = 1;
}
//因为celebration是从第次算起的
//所以转移矩阵的乘法,应该是乘以t-1次
--t;
while(t > 0)
{
if(t & 1)
{
memset(temp, 0, sizeof(temp));
for(i = 1; i <= n; ++i)
{
for(j = 1; j <= n; ++j)
{
for(k = 1; k <= n; ++k)
{
if(Transform[i][k] && result[k][j])
{
//因为矩阵的元素不是就是
//而在这个if循环内,Transform[i][k] * result[k][j] = 1
//所以可以使用异或的位运算来简化计算
temp[i][j] ^= Transform[i][k] * result[k][j];
}
}
}
}
memcpy(result, temp, sizeof(result));
}
t = t >> 1;
memset(temp, 0, sizeof(temp));
for(i = 1; i <= n; ++i)
{
for(j = 1; j <= n; ++j)
{
for(k = 1; k <= n; ++k)
{
if(Transform[i][k] && Transform[k][j])
{
temp[i][j] ^= Transform[i][k] * Transform[k][j];
}
}
}
}
memcpy(Transform, temp, sizeof(Transform));
}
//output
memset(EndState, 0, sizeof(EndState));
for(i = 1; i <= n; ++i)
{
for(j = 1; j <= n; ++j)
{
if (BeginState[j] && result[j][i])
{
EndState[i] ^= BeginState[j] * result[j][i];
}
}
}
int winner = 0;
for(i = 1; i <= n; ++i)
{
if(1 == EndState[i])
{
++winner;
}
}
printf("%d/n", winner);
return;
}
int main()
{
scanf("%d", &X);
while(X--)
{
init();
run();
}
return 0;
}