zoukankan      html  css  js  c++  java
  • jzoj5894. 【NOIP2018模拟10.5】同余方程

    Description

    在这里插入图片描述

    Input

    在这里插入图片描述

    Output

    在这里插入图片描述

    Sample Input

    123 1234 234 2345 5

    Sample Output

    470244

    Data Constraint

    在这里插入图片描述

    题解

    这道题真的是一道传说中的想法超级简单而实现起来细节超级多超级繁琐的题。
    调了我两天
    废话不多说。
    30%直接暴力
    60%据说可以用trie做。然而我不会
    100%
    我们观察一下题目。
    我们发现,我们设一个函数f(a,b)表示0 ~ a和0 ~ b这范围内的两两xor值为m的方案。
    答案即为:f(r1,r2)f(l11,r2)f(r1,l21)+f(l11,l21)f(r1,r2)-f(l1-1,r2)-f(r1,l2-1)+f(l1-1,l2-1)
    我们又发现,题目实际上可以用类似于数形dp的套路,把一个数分成“1001101……”的形式,然后处理。
    那么对于两个上界a,b。我们如何统计0 ~ a与0 ~ b的值呢?
    首先把a,b拆成二进制,然后我们就从高位往低位枚举;
    我们找到当前位置为1的位置,把当前位置看做是0,那么左边就是全部与原来的a(b)相同的,右边则是不定的,怎么填数字都是可以的(比上界小)。
    在这里插入图片描述
    (红色为确定的,蓝色为当前点,要变成0,黄色为不定的)
    然后,我们考虑把当前这两种情况给xor起来,就会发现:
    在这里插入图片描述
    那么,就会分成三种情况:红色为确定的,绿色为一半确定,一半不定,黄色是全部不确定的。
    我们就看看如何记录答案。
    对于一个新的C的值,我们要使得C确定时有多少方案,那么红色确定,绿色虽然不确定,但要符合C的值,所以也是确定的。
    然而对于这个黄色,它要变成一个确定的,那么就有2p2^p(p为黄色段的长度)
    我们再回到题目,发现A xor B|m,那么我们当前的这个C就是在op2p+qop*2^{p+q}(q为绿色段的长度,op为红色段的值。)到op2p+q+2p+q1op*2^{p+q}+2^{p+q}-1
    也就是:在这里插入图片描述
    我们就要在上面的两个式子中找到是m倍数的个数再乘上2p2^p即可。
    关于找r~l之间是m倍数的个数:r/m-(l-1)/m
    很多细节,自己慢慢玩:

    var
            i,j,k,l,n:longint;
            l1,r1,l2,r2,m,answer:int64;
            mi:array[0..63] of int64;
            mo:int64=998244353;
    function f(a,b:int64):int64;
    var
            i,j,k,upa,upb:longint;
            ta,tb,ja,jb:array[0..100] of longint;
            op,sa,sb,an,l,r,pp:int64;
    begin
            fillchar(ja,sizeof(ja),0);
            fillchar(jb,sizeof(jb),0);
            op:=a;upa:=0;upb:=0;
            while op>0 do
            begin
                    op:=op div 2;
                    inc(upa);
            end;
            op:=a;
            j:=1;
            for i:=upa downto 1 do
            begin
                    ja[i]:=op mod 2;
                    op:=op div 2;
            end;
            op:=b;
            while op>0 do
            begin
                    op:=op div 2;
                    inc(upb);
            end;
            op:=b;
            j:=1;
            for i:=upb downto 1 do
            begin
                    jb[i]:=op mod 2;
                    op:=op div 2;
            end;
            f:=0;
            sa:=0;
            for i:=1 to upa do
            begin
                    if ja[i]=1 then
                    begin
                    ta[i]:=0;
                    sb:=0;
                    for j:=1 to upb do
                    begin
                            if jb[j]=1 then
                            begin
                            tb[j]:=0;
                            if (upa-i)>(upb-j) then
                            begin
                                    op:=sa xor (sb div mi[(upa-i)-(upb-j)]);
                                    an:=mi[upb-j] mod mo;
                                    op:=op mod m;
                                    l:=op*mi[upa-i];
                                    r:=op*mi[upa-i]+mi[upa-i]-1;
                                    pp:=(r div m-(l-1) div m) mod mo;
                                    if l=0 then inc(pp);
                                    f:=(f+(pp*an) mod mo) mod mo;
                            end
                            else
                            begin
                                    op:=sb xor (sa div mi[(upb-j)-(upa-i)]);
                                    an:=mi[upa-i] mod mo;
                                    op:=op mod m;
                                    l:=op*mi[upb-j];
                                    r:=op*mi[upb-j]+mi[upb-j]-1;
                                    pp:=(r div m-(l-1) div m) mod mo;
                                    if l=0 then inc(pp);
                                    f:=(f+(pp*an) mod mo) mod mo;
                            end;
                            end;
                            tb[j]:=jb[j];
                            sb:=(sb+tb[j])*2;
                    end;
                    fillchar(tb,sizeof(tb),0);
                    end;
                    ta[i]:=ja[i];
                    sa:=(sa+ta[i])*2;
            end;
            fillchar(tb,sizeof(tb),0);
            ta:=ja;
            sa:=a;
            sb:=0;
            if upa>0 then
            for j:=1 to upb do
            begin
                    if jb[j]=1 then
                    begin
                    tb[j]:=0;
                    if (upa-i)>(upb-j) then
                    begin
                            op:=sa xor (sb div mi[(upa-i)-(upb-j)]);
                            an:=mi[upb-j] mod mo;
                            op:=op mod m;
                            l:=op*mi[upa-i];
                            r:=op*mi[upa-i]+mi[upa-i]-1;
                            pp:=(r div m-(l-1) div m) mod mo;
                            if l=0 then inc(pp);
                            f:=(f+(pp*an) mod mo) mod mo;
                    end
                    else
                    begin
                            op:=sb xor (sa div mi[(upb-j)-(upa-i)]);
                            an:=mi[upa-i] mod mo;
                            op:=op mod m;
                            l:=op*mi[upb-j];
                            r:=op*mi[upb-j]+mi[upb-j]-1;
                            pp:=(r div m-(l-1) div m) mod mo;
                            if l=0 then inc(pp);
                            f:=(f+(pp*an) mod mo) mod mo;
                    end;
                    end;
                    tb[j]:=jb[j];
                    sb:=(sb+tb[j])*2;
            end;
            tb:=jb;
            fillchar(ta,sizeof(ta),0);
            sb:=b;
            sa:=0;
            if upb>0 then
            for i:=1 to upa do
            begin
                    if ja[i]=1 then
                    begin
                    ta[i]:=0;
                    if (upa-i)>(upb-j) then
                    begin
                            op:=sa xor (sb div mi[(upa-i)-(upb-j)]);
                            an:=mi[upb-j] mod mo;
                            op:=op mod m;
                            l:=op*mi[upa-i];
                            r:=op*mi[upa-i]+mi[upa-i]-1;
                            pp:=(r div m-(l-1) div m) mod mo;
                            if l=0 then inc(pp);
                            f:=(f+(pp*an) mod mo) mod mo;
                    end
                    else
                    begin
                            op:=sb xor (sa div mi[(upb-j)-(upa-i)]);
                            an:=mi[upa-i] mod mo;
                            op:=op mod m;
                            l:=op*mi[upb-j];
                            r:=op*mi[upb-j]+mi[upb-j]-1;
                            pp:=(r div m-(l-1) div m) mod mo;
                            if l=0 then inc(pp);
                            f:=(f+(pp*an) mod mo) mod mo;
                    end;
                    end;
                    ta[i]:=ja[i];
                    sa:=(sa+ta[i])*2;
            end;
            ta:=ja;
            tb:=jb;
            sa:=a;sb:=b;
            if (upa>0) and (upb>0) then
            begin
            if (upa-i)>(upb-j) then
            begin
                    op:=sa xor (sb div mi[(upa-i)-(upb-j)]);
                    an:=mi[upb-j] mod mo;
                    op:=op mod m;
                    l:=op*mi[upa-i];
                    r:=op*mi[upa-i]+mi[upa-i]-1;
                    pp:=(r div m-(l-1) div m) mod mo;
                    if l=0 then inc(pp);
                    f:=(f+(pp*an) mod mo) mod mo;
            end
            else
            begin
                    op:=sb xor (sa div mi[(upb-j)-(upa-i)]);
                    an:=mi[upa-i] mod mo;
                    op:=op mod m;
                    l:=op*mi[upb-j];
                    r:=op*mi[upb-j]+mi[upb-j]-1;
                    pp:=(r div m-(l-1) div m) mod mo;
                    if l=0 then inc(pp);
                    f:=(f+(pp*an) mod mo) mod mo;
            end;
            end;
            if (a=0) and (b>0) then
            begin
            sb:=0;
            for j:=1 to upb do
            begin
                    if jb[j]=1 then
                    begin
                    tb[j]:=0;
                    op:=sb xor (sa div mi[(upb-j)]);
                    an:=1;
                    op:=op mod m;
                    l:=op*mi[upb-j];
                    r:=op*mi[upb-j]+mi[upb-j]-1;
                    pp:=(r div m-(l-1) div m) mod mo;
                    if l=0 then inc(pp);
                    f:=(f+(pp*an) mod mo) mod mo;
                    end;
                    tb[j]:=jb[j];
                    sb:=(sb+tb[j])*2;
            end;
            if (b xor 0) mod m=0 then inc(f);
            end
            else
            if (a>0) and (b=0) then
            begin
            sa:=0;
            for i:=1 to upa do
            begin
                    if ja[i]=1 then
                    begin
                    ta[i]:=0;
                    op:=sa xor (sb div mi[(upa-i)]);
                    an:=1;
                    op:=op mod m;
                    l:=op*mi[upa-i];
                    r:=op*mi[upa-i]+mi[upa-i]-1;
                    pp:=(r div m-(l-1) div m) mod mo;
                    if l=0 then inc(pp);
                    f:=(f+(pp*an) mod mo) mod mo;
                    end;
                    ta[i]:=ja[i];
                    sa:=(sa+ta[i])*2;
            end;
            if (a xor 0) mod m=0 then inc(f);
            end
            else
            if (a=0) and (b=0) then
            begin
                    f:=1;
            end;
    end;
    begin
            assign(input,'mod.in');reset(input);
            assign(output,'mod.out');rewrite(output);
            mi[0]:=1;
            for i:=1 to 62 do
            begin
                    mi[i]:=mi[i-1]*2;
            end;
            readln(l1,r1,l2,r2,m);
            writeln((f(r1,r2)-f(l1-1,r2)-f(r1,l2-1)+f(l1-1,l2-1)+mo) mod mo);
    end.
    
    
    
    我活在这夜里。无论周围多么黑暗,我都要努力发光!我相信着,终有一天,我会在这深邃的夜里,造就一道最美的彩虹。
  • 相关阅读:
    java课程之团队开发冲刺阶段1.10
    java课程之团队开发冲刺阶段1.9
    java课程之团队开发之用户模板和用户场景
    大二第二学期周学习进度总结(八)
    java课程之团队开发冲刺阶段1.8
    java课程课后作业190425之一维数组最大子数组—功能扩展(界面实现)
    java课程之团队开发冲刺阶段1.7
    java课程之团队开发冲刺阶段1.6
    Python函数-高级(闭包/装饰器)
    Python之函数
  • 原文地址:https://www.cnblogs.com/RainbowCrown/p/11148387.html
Copyright © 2011-2022 走看看