0%

CF1997F Chips on a Line

传送门

Solution

fibifib_i 为斐波那契数列的第 ii 项,cic_i 为第 ii 格的芯片数,那么当所有 cic_i 确定时,无论怎么操作,都能保证 k=fibicik=\sum fib_ic_i 不变。因此所有情况都可以变成在第一格上放置若干个芯片,其它格子上没有芯片。

gig_i 为第一格有 ii 个芯片,经过操作后,最少剩下多少芯片。求解 gig_i 可以类比为完全背包求能获得的最小价值。

fj,kf_{j,k} 表示 ci=j\sum c_i=jfibici=k\sum fib_ic_i=kcc 的数量。同样通过完全背包求解。

dp 最外层不能是 jj 的原因是会算重。

答案为将所有符合 gk=mg_k=mfn,kf_{n,k} 相加。

时间复杂度为 O(n2xfibx)O(n^2x\cdot fib_x)

Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

const ll N = 55005, mod = 998244353;

ll n, x, m, g[N], f[1005][N], tot, fab[N], ans;

int main()
{
scanf("%lld%lld%lld", &n, &x, &m);
fab[1] = 1;
for (int i = 2; i <= 24; i++)
fab[i] = fab[i - 1] + fab[i - 2];
tot = n * fab[x];
memset(g, 0x3f, sizeof(g));
g[0] = 0;
for (int i = 1; i <= 24; i++)
for (int j = fab[i]; j <= tot; j++)
g[j] = min(g[j], g[j - fab[i]] + 1);
f[0][0] = 1;
for (int i = 1; i <= x; i++)
for (int j = 1; j <= n; j++)
for (int k = fab[i]; k <= tot; k++)
f[j][k] = (f[j][k] + f[j - 1][k - fab[i]]) % mod;
for (int i = n; i <= tot; i++)
if (g[i] == m)
ans = (ans + f[n][i]) % mod;
printf("%lld", ans);
return 0;
}