题目大意:一棵树,第一年只有祖先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;
}


京公网安备 11010502036488号