AT2396 [ARC071D] Infinite Sequence
https://www.luogu.com.cn/problem/AT2396
不难发现,如果在一个 > 1 >1 >1的数后面放一个 > 1 >1 >1的数,那么这个序列就确定了
于是我们考虑倒过来DP
f [ i ] f[i] f[i]表示 [ i , n ] [i,n] [i,n]的序列个数
有3种转移
- 这一位为1, f [ i ] + = f [ i + 1 ] f[i]+=f[i+1] f[i]+=f[i+1]
- 这一位和下一位填 > 1 >1 >1的数 f [ i ] + = ( n − 1 ) ∗ ( n − 1 ) f[i]+=(n-1)*(n-1) f[i]+=(n−1)∗(n−1)
- 这一位填 k k k往后的 k k k位是1, f [ i ] + = f [ i + k + 1 ] f[i]+=f[i+k+1] f[i]+=f[i+k+1]
注意如果
i
+
k
+
1
>
n
i+k+1>n
i+k+1>n
f
[
i
+
k
+
1
]
=
1
f[i+k+1]=1
f[i+k+1]=1
容易用后缀和优化到
O
(
n
)
O(n)
O(n)
code:
#include<bits/stdc++.h>
#define ll long long
#define mod 1000000007
using namespace std;
int n;
ll f[1000050];
int main() {
scanf("%d", &n);
f[n] = n;
f[n - 1] = 1ll * n * n % mod;
ll s = 0;
for(int i = n - 2; i >= 1; i --) {
f[i] = f[i + 1];
f[i] = f[i] + 1ll * (n - 1) * (n - 1) % mod, f[i] %= mod;
s = (s + f[i + 3]) % mod;
f[i] = (f[i] + s) % mod;
f[i] = (f[i] + i + 1) % mod; // i+x+1>=n x>=n-i-1 -> n-x<=i+1
}
printf("%lld", f[1]);
return 0;
}