[ARC071F] Infinite Sequence

题意

让你构造一个每个数为1~n的无限长的序列,满足:

  1. 第n个数与它后面的数都相同

  2. 对于每一个数x,它和后面的x个数都相同。

问你有多少种方案。

题解

考虑dp,设 f [ i ] f[i] f[i]代表第i~n位都填好的方案数,倒着dp。

转移分3种情况:

当第i位是1时, f [ i ] + = f [ i + 1 ] f[i]+=f[i+1] f[i]+=f[i+1]

当第i位不是1并且第i+1位也不是1时,这个序列就只能长成 x y y y y y y y y y y y y . . . xyyyyyyyyyyyy... xyyyyyyyyyyyy...的样子了,其中 x x x y y y可以填任意非1数,所以 f [ i ] + = ( n − 1 ) ∗ ( n − 1 ) f[i]+=(n-1)*(n-1) f[i]+=(n1)(n1).

当第i位不是1但是第i+1位是1时,这个序列就长成 x 11111 S x11111S x11111S的样子了,所以对于每一个 x x x f [ i ] + = f [ i + x + 1 ] f[i]+=f[i+x+1] f[i]+=f[i+x+1](如果 i + x + 1 > n i+x+1>n i+x+1>n那么 f [ i + x + 1 ] = 1 f[i+x+1]=1 f[i+x+1]=1),维护一个 f f f的后缀和就可以做到 O ( 1 ) O(1) O(1)转移了。

时间复杂度: O ( n ) O(n) O(n)

代码:

#include 
using namespace std;

#define MAXN 1000010
#define mod 1000000007

int n,f[MAXN],add;

int main()
{
    scanf("%d",&n);
    f[n]=n;
    f[n-1]=(long long)n*n%mod;
    for(int i=n-2;i>=1;--i)
    {
        add=(add+f[i+3])%mod;
        f[i]=f[i+1];
        f[i]=(f[i]+(long long)(n-1)*(n-1)%mod)%mod;
        f[i]=(f[i]+add)%mod;
        f[i]=(f[i]+i+1)%mod;
    }
    printf("%d\n",f[1]);
}

你可能感兴趣的:(C++,题解,Atcoder)