简述题意:
一共n+1个房间,一个人从1走到n+1,如果第奇数次走到房间i,会退回到房间Pi,如果偶数次走到房间i,则走到房间i+1,问走到n+1需要多少步,结果对1e9+7取模。
算法:思维+DP
难度:NOIP+
题解:设dp[i]表示从1走到i需要多少步,那么走到房间i+1需要dp[i+1]=dp[i]+1+x+1,这里面第一个1表示走完这步退回到Pi,这个x表示退回到房间Pi再走回来的步数,第二个1表示走完这步到达i+1。我们发现:1.当走到房间Pi的时候,Pi+1到i都是没有走过的即为0次;2.当走到房间i的时候,Pi+1到i这段一定都走过了偶数次,因为奇数次是不会放你过来的,一定都是偶数次才能走到i这步,所以说状态相同。x就是从Pi走到i所需要的步数,那么x=dp[i]-dp[p[i]],所以状态转移方程是dp[i+1]=dp[i]+1+dp[i]-dp[p[i]]+1。值得注意在结果对1e9+7取模,取模的时候要先+mod再%mod,其中涉及到减法可能有负数,前面每个数都是取模过的数,dp[i]是很可能小于dp[p[i]]的,当然如果都不取模的话dp数组肯定是递增的。
代码如下:
#include <bits/stdc++.h>
#define ll long long
#define N 1000005
using namespace std;
const ll mod=1e9+7;
ll p[N],dp[N];
int main()
{
freopen("rideon.in","r",stdin);
freopen("rideon.out","w",stdout);
int n;
scanf("%d",&n);
for(int i = 1;i <= n;i++)
scanf("%I64d",&p[i]);
dp[1]=0;
for(int i = 1;i <= n;i++)
dp[i+1]=(dp[i]+1+dp[i]-dp[p[i]]+1+mod)%mod;
printf("%I64d\n",dp[n+1]);
return 0;
}