zoukankan      html  css  js  c++  java
  • BZOJ4926 皮皮妖的递推

    第二次乱出题。
    为了方便,以m=2为例,把原式变一下形,得f(i)+f(f(i-1))=i
    我们先无视掉那个-1,我们发现:诶,这个东西好像斐波那契数列。
    具体地,我们用f(n)表示把n用斐波那契数列进行拆分后,每一项的前一项的和。
    例:20=13+5+2,f(20)=8+3+1
    我们惊奇的发现现在已经可以满足f(i)+f(f(i))=i这个式子了。
    但是现在有个-1,怎么办呢,其实很简单,我们定义斐波那契数列第0项为1即可。
    证明:设$g_0=g_1=g_2=1,g_i=g_{i-1}+g_{i-2},n=sum_{i=1}^kg_{a_i}$
    我们考虑n-1的形式。
    1.
    n-1与n的前k-1项一定相同,所以在前k-1项满足这个式子。
    2.
    当n的第k项为1时,n-1没有第k项,此时1+0=1,满足这个式子。
    3.
    否则当n的第k项不为1时,你会发现$f(f(g_{a_k}-1))=g_{a_{k-2}}$
    这个东西不好说明,举个例子
    $g_{a_k}=34=21+8+3+1+1$
    $g_{a_k}-1=21+8+3+1$
    $f(f(g_{a_k}))=8+3+1+1=13=g_{a_{k-2}}$
    这就是为什么我要把第0项设成1的原因,所以第k项也满足。
    证毕。

    当m更大时,只需把g的递推式改为$g_i=g_{i-1}+g_{i-m}$即可。

    #include <cstdio>
    
    int m,t;
    long long n,a1,f[5000005];
    
    int main() {
        scanf("%lld%d",&n,&m);
        for(int i=0;i<=m;i++) f[i]=1;
        for(int i=m+1;;i++) {
            f[i]=f[i-1]+f[i-m];
            if(f[i]>n) {t=i-1; break;}
        }
        for(int i=t;n;i--) if(f[i]<=n) n-=f[i],a1+=f[i-1];
        printf("%lld",a1);
        return 0;
    }
  • 相关阅读:
    每日总结59
    每日总结58
    每日总结57
    每日总结56
    每日总结55
    每日总结54
    每日总结53
    每日总结52
    学习日报
    学习日报
  • 原文地址:https://www.cnblogs.com/juruolty/p/7001568.html
Copyright © 2011-2022 走看看