存在n+1个房间,每个房间依次为房间1 2 3...i,每个房间都存在一个传送门,i房间的传送门可以把人传送到房间pi(1<=pi<=i),现在路人甲从房间1开始出发(当前房间1即第一次访问),每次移动他有两种移动策略:
A. 如果访问过当前房间 i 偶数次,那么下一次移动到房间i+1;
B. 如果访问过当前房间 i 奇数次,那么移动到房间pi;
现在路人甲想知道移动到房间n+1一共需要多少次移动;
第一行包括一个数字n(30%数据1<=n<=100,100%数据 1<=n<=1000),表示房间的数量,接下来一行存在n个数字 pi(1<=pi<=i), pi表示从房间i可以传送到房间pi。
输出一行数字,表示最终移动的次数,最终结果需要对1000000007 (10e9 + 7) 取模。
2 1 2
4
开始从房间1 只访问一次所以只能跳到p1即 房间1, 之后采用策略A跳到房间2,房间2这时访问了一次因此采用策略B跳到房间2,之后采用策略A跳到房间3,因此到达房间3需要 4 步操作。
#解析:https://blog.csdn.net/weixin_42001089/article/details/87114410 n = int(input()) home = [int(e)-1 for e in input().split()] dp = [0 for _ in range(n+1)] dp[1] = 2 for i in range(2,n+1): dp[i] = 2*dp[i-1] - dp[home[i-1]]+2 print(dp[n]%1000000007)
#include <iostream>usingnamespacestd;longlongconstm=1000000007;intmain(){intn;while(cin>>n){intp[n+1];p[0]=0;for(inti=1; i<=n; i++)cin>>p[i];longlongdp[n+1];for(inti=0; i<=n; i++){dp[i]=0;}dp[2]=2;for(inti=3; i<=n; i++){dp[i]=(dp[i-1]+1+dp[i-1]-dp[p[i-1]]+1)%m;}cout << ((dp[n]+1+dp[n]-dp[p[n]]+1)%m+m)%m << endl;}}
def helper(nums, n): dp = [[0, 0] for _ in range(n + 2)] dp[1][0] = 1 dp[1][1] = 0 for i in range(2, n + 2): dp[i][1] = dp[i - 1][0] + 1 if i == n + 1: break dp[i][0] = 2 * dp[i][1] + 1 - dp[nums[i - 1]][1] return dp[n + 1][1] % 1000000007 n = int(input()) home = list(map(int, input().strip().split())) print(helper(home, n))
//1000000007都是为了避免溢出,实际上是dp[i+1]=dp[i]-dp[pi-1]+2+dp[i]#include <iostream>usingnamespacestd;intmain() {intn;while(cin>>n){intdp[n+1]={0};intpi,tmp;for(inti=0;i<n;i++){cin>>pi;tmp=dp[i]<dp[pi-1]?dp[i]+1000000007:dp[i];dp[i+1]=(2*tmp-dp[pi-1]+2)%1000000007;}cout<<dp[n]%1000000007<<endl;}}
''' 上面BPSK大佬有些我自己编的事例通不过,比如 (3 \n 1 2)做了一点修改。 ''' n = int(input()) home = [int(e)-1 for e in input().split()] dp = [0 for _ in range(n+1)] dp[1] = 2 id_pi = 0 for i in range(2,n+1): if id_pi<len(home)-1: if home[id_pi+1]<=i: id_pi+=1 dp[i] = 2*dp[i-1] - dp[home[id_pi]]+2 print(dp[n]%1000000007)
#递归求解,f(i+1)= 2 * f(i) - f(p(i)) + 2 n = int(input())
A = [0] + [int(i) for i in input().split()]
i = 0
B = (len(A)+2)*[0]
cnt = 0
for i in range(3,n+2):
B[1] = 0
B[2] = 2
B[i] = 2*B[i-1] - B[A[i-1]] + 2
print(B[n+1]%1000000007)
此题是一个分析规律,总结递推公式的问题。
设首次到达i号位置所需的次数为f(i)。由题设规则容易知道,到达某个点后,若到达次数为奇数,一定会从该点再次返回到该点以前的位置(pi <= i),那么此后一定会再次到达该点,此时到达次数为偶数,跳转到i + 1,显然到达点i时,点1<=j<i的访问次数均为偶数次。
考虑第1次到达i点,已经使用的步数为f(i),跳转到pi点使用步数1,此时pi点已经访问过的次数为偶数,那么再次到达pi的访问次数为奇数次,则再次重复从pi到i的访问路径,显然这条访问路径的步数为f(i - 1) - f(pi)。然后再次到达i点,此时为第二次到达,转移到i+1,在需要1次。总的步数即为f(i) + (1 + f(i - 1) - f(pi)) + 1 = 2 * f(i) - f(p(i)) + 2。由此递推公式,即可依次计算出i = 1, 2, ..., n, n + 1