高中Oj1434. 灌水

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.


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值