Description
学生都很喜欢灌水,第一天只有Alice给她的每个朋友灌了一次水,从第二天开始,所有学生(包括Alice)将会有规律地去灌水:
•如果前一天被灌了奇数次的水,他们将会给每个朋友灌一次水;
•如果前一天被灌了偶数次的水,他们将会给每个朋友灌两次水。
学生编号为1到N,Alice为1号,学生之间的朋友关系会给出。
计算H天后一共灌了几次水。
Input
输入一行包含两个整数N和H(1<=N<=20,1<=H<=10^9),表示学生数和天数。
接下来N行,每行包含N个‘0’或‘1’,(A,B)处的字符表示A和B的关系,‘1’表示是朋友关系,‘0’表示不是。注意自己和自己不是朋友关系,输入保证该矩阵是对称的。
Output
输出H天后一共灌水的数量。
Sample Input
输入1: 4 1 0110 1001 1001 0110 输入2: 4 2 0110 1001 1001 0110 输入3: 5 3 01000 10110 01000 01001 00010
Sample Output
输出1: 2 输出2: 14 输出3: 26
Data Constraint
Hint
【样例解释】
样例2中,第一天Alice灌了2次水,第二天学生1和学生4给学生2和学生3都灌了2次水,而学生2和学生3给学生1和学生4各灌水1次,2天一共灌了12次水。
【数据范围】
50%的数据 H<=1000。
正解
因为H这么大,我们一想就能想到肯定有规律可循。我们可以发现,当这个序列经过一定的次数后,全都是偶数,这时就开始循环了。我们只用记录它的状态、时间,去找循环节即可。
CODE
var
ji:array[0..30,0..100000]of longint;
sum,bz:array[0..1000010]of int64;
a,new:array[0..100000]of longint;
ans,ans1,bz1:int64;
n,m,i,j,k:longint;
ch:char;
begin
readln(n,m);
for i:=1 to n do begin
for j:=1 to n do begin
read(ch);
if ch='1' then begin
inc(ji[i,0]);
ji[i,ji[i,0]]:=j;
end;
end;
readln;
end;
for i:=1 to ji[1,0] do a[ji[1,i]]:=1;
sum[1]:=ji[1,0];
for i:=1 to n do
if odd(a[i]) then ans:=ans+1 shl (i-1);
bz[ans]:=1;
for i:=2 to m do begin
bz1:=0;ans:=0;ans1:=0;
for j:=1 to n do begin
if a[j] mod 2=0 then begin
ans:=ans+ji[j,0]*2;
for k:=1 to ji[j,0] do inc(new[ji[j,k]],2);
end
else begin
ans:=ans+ji[j,0];
for k:=1 to ji[j,0] do inc(new[ji[j,k]]);
end;
end;
for j:=1 to n do begin
a[j]:=new[j];
new[j]:=0;
if odd(a[j]) then ans1:=ans1+1 shl (j-1);
end;
sum[i]:=sum[i-1]+ans;
if bz[ans1]<>0 then begin
ans:=(m-bz[ans1]) div (i-bz[ans1])*(sum[i]-sum[bz[ans1]]);
ans:=ans+sum[bz[ans1]+(m-bz[ans1]) mod (i-bz[ans1])];
writeln(ans);
halt;
end
else bz[ans1]:=i;
end;
writeln(sum[m]);
end.