1 条题解

  • 0
    @ 2025-8-24 22:12:47

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar Pisces
    AFO || QwQ

    搬运于2025-08-24 22:12:47,当前版本为作者最后更新于2019-11-09 16:27:28,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    题面在此

    大波公式警告\Large\text{大波公式警告}

    为了方便,以下我用lg\lg来代替log2\log_2

    我们容易得出$ans=F(n)=F(\lfloor n/2\rfloor )+F(\lceil n/2\rceil )+n-1(n>1)$,我们令$g(n)=g(\lfloor n/2\rfloor )+g(\lceil n/2\rceil )+a(n)(n>1)$,则有$\Delta g(n)=\Delta a(n)+\Delta g(\lfloor n/2\rfloor)$

    我们有恒等式lg2j=lgj+1\lceil \lg2j\rceil=\lceil \lg j\rceil+1和$\lceil \lg(2j-1)\rceil=\lceil \lg j\rceil+[j>1](j\geq1)$,所以当a(n)=n1a(n)=n-1时,lg(n+1)\lceil \lg(n+1)\rceil满足Δf(n)=1+Δf(n/2)\Delta f(n)=1+\Delta f(\lfloor n/2\rfloor)

    所以有结论若$F(1)=0,F(n)=F(\lfloor n/2\rfloor )+F(\lceil n/2\rceil )+n-1(n>1)$,F(n)=k=1nlgkF(n)=\sum\limits_{k=1}^{n}\lceil \lg k\rceil,我们就可以暴力求F(n)F(n),但此时暴力仍然是O(n)O(n)的,因为其中有一些连续相等的数,可以考虑数论分块,复杂度大概是O(lgn)O(\lg n)的,预计得分1020pts10\sim20pts

    m=lgnm=\lceil \lg n\rceil,我们考虑增加2mn2^m-n项以简化运算:

    $F(n)+(2^m-n)m=\sum\limits_{k=1}^{2^m}\lceil \lg k\rceil=\sum\limits_{j,k}j[j=\lceil \lg k\rceil][1\leq k\leq 2^m]=\sum\limits_{j,k}j[2^{j-1}\lt k\leq 2^j][1\leq j\leq m]=\sum\limits_{j=1}^{m}j2^{j-1}=2^m(m-1)+1$

    所以我们得到F(n)=nm2m+1F(n)=nm-2^m+1

    但是还有一个问题:如何求lgn\lceil \lg n\rceil,由于nn太大,只能使用高精度,考虑暴力求2k2^k,暴力找到mm,暴力取模,复杂度仍为O(lgn)O(\lg n),预计得分仍然为1020pts10\sim20pts

    我们有换底公式$\lg n=\log_{10}n/\log_{10}2=\log_{10}n*(1/\log_{10}2),\log_{10}n$可以用数位个数估算(偏小),1/log1021/\log_{10}2取估算值3.321928094887362181708567732133.32192809488736218170856773213,此时就可以求得估算值ll,考虑预处理出22l2^{2^l},再把ll用二进制法表示即可快速求出2l2^l,再用暴力即可(此时暴力最多算44次,因为24>102^4\gt10),复杂度O(lglgn)O(\lg \lg n),预计得分100pts100pts,但是此题数据范围达到1010000010^{100000},必须用FFTFFT优化,否则得分只能是5080pts50\sim80pts

    (当然高精度快速幂是一样的)

    但其实这道题还有个比较巧妙的理解方法:

    先求式子:$f(n)=f(\lfloor n/2\rfloor )+f(\lceil n/2\rceil )+n(n>1)$,n/2,n/2\lfloor n/2\rfloor,\lceil n/2\rceil取遍了nn,如果每次加nn,就相当于每层递归都是加nn,一共递归了lgn\lceil \lg n\rceil,且一共递归了n1n-1,答案就是f(n)(n1)f(n)-(n-1),所以我们还是得到F(n)=nm2m+1F(n)=nm-2^m+1

    Code:(part)Code:(part)

    int main()
    {
        scanf("%s",ch);n=ch;
        int l=db*(strlen(ch)-1),ll=l;//db=3.32192809488736218170856773213
        for(register int i=1;i<=l;i<<=1,++tot)
            b[tot+1]=b[tot]*b[tot];//预处理
        while(l){
            if(l&1) s=s*b[t];//二进制分解算
            ++t,l>>=1;
        }
        while(1){//暴力算
            s+=s,++ll;
            if(s>=n) break;
        }
        T=(n%mod*ll+mod-qpow(2,ll)+1)%mod;
        T.print();
        return 0;
    }
    
    • 1

    信息

    ID
    4548
    时间
    100ms
    内存
    128MiB
    难度
    6
    标签
    递交数
    0
    已通过
    0
    上传者