• 停不下来的团长奥尔加


    2020.11.2

    题目描述

    奥尔加在一个长度为 (n+1) 的街道上跑着,初始,奥尔加在位置 (1) 上,他想要跑到位置 (n+1) 去保护团员 ride on。空旷的大路上难免会有暗杀者,当奥尔加走到位置 (i) 时,会有暗杀者出现,这时奥尔加只能回到 (p_i (1leq p_ileq i)) 位置上,但在下次到达 (i) 的时候,暗杀者就不会出现(如果再到达 (i) 还会有暗杀者),换言之,当奥尔加此时是第奇数次到达 (i) 的时候,下一步会走到 (p_i),第偶数次到达 (i) 的时候,下一步走到 (i+1)(n+1) 位置上没有暗杀者)。奥尔加每次移动都需要花费 (1) 单位时间,停不下来的奥尔加只会一直跑,他想知道自己什么时候才能到达 (n+1) 位置,因为答案可能会很大,你只需要告诉他答案对 (1000000007 (10^9+7)) 取模的结果就好了。

    解法

    一开始想的分层图,什么玩意儿啊……后来想dp,最后三分钟把式子推出来了……没时间写

    (dp_i) 表示第一次走到 (i) 的时候是第几步,那么答案就是 (dp_{n+1})
    (f_i) 表示当前在位置 (i),跳到 (p_i) 后再次到达位置 (i) 需要的步数。

    那么

    [egin{cases} dp_1=0 \ f_1=1 \ dp_n=dp_{n-1}+f_{i-1}+1 \ f_n=(sum_{i=a_i}^{n-1} f_i+1)+1 end{cases}]

    (f_n) 的转移前缀做差即可。

    #include<stdio.h>
    #define ll long long
    #define N 1000007
    #define Mod 1000000007
    
    inline int read(){
        int x=0; bool flag=1; char c=getchar();
        while(c<'0'||c>'9'){if(c=='-') flag=0;c=getchar();}
        while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-48;c=getchar();}
        return flag? x:-x;
    }
    
    ll dp,f[N],s[N];
    int n,a[N];
    int main(){
        freopen("rideon.in","r",stdin);
        freopen("rideon.out","w",stdout);
        n=read(),a[1]=read();
        dp=0,f[1]=s[1]=1;
        for(int i=2;i<=n;i++){
            int x=read();
            dp=(dp+f[i-1]+1)%Mod;
            f[i]=((s[i-1]-s[x-1]+i-x+1)%Mod+Mod)%Mod;
            s[i]=(s[i-1]+f[i])%Mod;
        }
        printf("%lld",dp+f[n]+1);
    }
    
  • 相关阅读:
    使用手机对Tomcat发布的web应用进行测试
    JavaScript HTML DOM 事件
    JavaScript HTML DOM
    初学JavaScript
    Myeclipse中Servlet的创建
    RequestDispatcher.forward() 方法和HttpServletResponse.sendRedirect()方法的区别
    获取当前系统的时间转化成Long型
    JS实现时间格式化
    用小技巧来优化大数据量的网页
    文字超长自动省略,以...代替,CSS实现
  • 原文地址:https://www.cnblogs.com/wwlwQWQ/p/13917628.html
Copyright © 2020-2023  润新知