不想说啥了,比赛期间智商全程下线
A
设$f[i][j]$表示前$i$个位置,前缀和为$j$的方案数,转移的时候该位置放了什么,以及该位置之前的和是多少。
发现第二维可以前缀和优化。
不用管代码里的fib是什么,当时傻了在xjb分析下界。。。。
时间复杂度:$O(nk)$
/* */ #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<map> #include<vector> #include<set> #include<queue> #include<cmath> //#include<ext/pb_ds/assoc_container.hpp> //#include<ext/pb_ds/hash_policy.hpp> #define Pair pair<int, int> #define MP(x, y) make_pair(x, y) #define fi first #define se second #define int long long #define LL long long #define ull unsigned long long #define rg register #define pt(x) printf("%d ", x); //#define getchar() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1<<22, stdin), p1 == p2) ? EOF : *p1++) //char buf[(1 << 22)], *p1 = buf, *p2 = buf; //char obuf[1<<24], *O = obuf; //void print(int x) {if(x > 9) print(x / 10); *O++ = x % 10 + '0';} //#define OS *O++ = ' '; using namespace std; //using namespace __gnu_pbds; const int MAXN = 1e6 + 10, INF = 1e9 + 10, mod = 998244353; const double eps = 1e-9; inline int read() { char c = getchar(); int x = 0, f = 1; while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();} while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar(); return x * f; } int f[21][MAXN], s[MAXN], fib[MAXN]; main() { int N = read(), K = read();//k个位置 总和为n fib[1] = 1; fib[2] = 1; for(int i = 3; i <= N; i++) fib[i] = fib[i - 1] + fib[i - 2]; for(int i = 1; i <= N; i++) f[1][i] = 1, s[i] = (s[i - 1] + f[1][i]) % mod; for(int i = 2; i <= K; i++) { for(int j = 1; j <= N; j++) { // for(int k = fib[i - 1]; k <= j / 2; k++) (f[i][j] += f[i - 1][k]) %= mod; f[i][j] = s[j / 2] % mod; if((j / 2 >= fib[i - 1]) && (fib[i - 1] >= 1)) f[i][j] = (f[i][j] - s[fib[i - 1] - 1] + mod) % mod; } s[0] = 0; for(int j = 1; j <= N; j++) s[j] = (s[j - 1] + f[i][j]) % mod; } printf("%d", f[K][N] % mod); return 0; } /* 15 3 */