https://jzoj.net/senior/#main/show/1434
这道题的暴力是显然的,我们只需对上一次灌水做一个标记,判断是被灌了奇数次还是偶数次,奇数次的再去改变其他人的状态即可。
注意,这里n<=20,那么对于每一个人的标记总数只有2^20种,而h却为10^9,很明显我们可以采取周期策略。
如下图:
代码:
var
date,value:Array[0..1500000] of int64;
x:array[1..20] of longint;
bz:array[1..20] of boolean;
ch:array[1..20,1..20] of char;
n,h,i,j,k,ans,sum,w,xmod,xdiv:Longint;
begin
readln(n,h);
for i:=1 to n do
begin
for j:=1 to n do
read(ch[i,j]);
readln;
end;
for i:=1 to n do
if ch[1,i]='1' then
begin
bz[i]:=true;
inc(ans);
end;
for k:=1 to h-1 do
begin
w:=0;
for i:=1 to n do
if bz[i] then inc(w,1 shl (i-1));
if date[w]=0 then
begin
date[w]:=k;
value[k]:=ans;
end
else
begin
value[k]:=ans;
xmod:=(h-k) mod (k-date[w]);
xdiv:=(h-k) div (k-date[w]);
writeln(xdiv*(value[k]-value[date[w]])+value[date[w]+xmod]-value[date[w]]+value[k]);
halt;
end;
fillchar(x,sizeof(x),0);
sum:=0;
for i:=1 to n do
if bz[i] then
begin
for j:=1 to n do
if ch[i,j]='1' then
begin
inc(x[j]);
inc(sum);
end;
end
else
begin
for j:=1 to n do
if ch[i,j]='1' then inc(sum,2);
end;
inc(ans,sum);
fillchar(bz,sizeof(bz),0);
for i:=1 to n do
if x[i] mod 2=1 then bz[i]:=true;
end;
writeln(ans);
end.