题目大意:一棵树,第一年只有祖先0;每一年,0可以分支出1个1,0可以分支出1个0和1个1,n年后共有多少个结点?

图片说明

f[i][j]表示第i年数字j的数量:

f[i][0] = f[i-1][1],因为只有1能得到0;

f[i][1] = f[i-1][0]+f[i-1][1],因为0和1都能够得到1。

询问比较多,要预处理出10000000以内的所有答案,O(1)回答询问。

只有加法,用减法代替取模,同时避免开long long爆空间。

#include <stdio.h>
#define N 10000005
#define mo 998244353
int t, n, m, i, j, k, f[N][2], s[N];
int main(){
    f[1][0] = f[2][1] = 1;
    s[1] = 1, s[2] = 2;
    for(i=3; i<N; i++){
        f[i][0] = f[i-1][1];
        f[i][1] = f[i-1][0] + f[i-1][1];
        if(f[i][1] >= mo) f[i][1] -= mo;
    }
    for(i=3; i<N; i++){
        s[i] = s[i-1] + f[i+1][1];
        if(s[i] >= mo) s[i] -= mo;
    }
    scanf("%d", &t);
    while(t--){
        scanf("%d", &n);
        printf("%d\n", s[n]);
    }
    return 0;
}

压缩空间:

#include <stdio.h>
#define N 10000005
#define mo 998244353
int t, n, m, i, j, k, a, b, pa, pb, s[N];
int main(){
    pa = 0, pb = s[1] = 1;
    for(i=3; i<N; i++){
        a = pb, b = pa + pb;
        if(b >= mo) b -= mo;
        s[i-1] = s[i-2] + b;
        if(s[i-1] >= mo) s[i-1] -= mo;
        pa = a, pb = b;
    }
    scanf("%d", &t);
    while(t--){
        scanf("%d", &n);
        printf("%d\n", s[n]);
    }
    return 0;
}