// #include [HTML_REMOVED]
// #include [HTML_REMOVED]
// #include [HTML_REMOVED]
// using namespace std;
// typedef long long LL;
// const int N = 55, M = 10;
// LL f[N][M];
// //f[i][j]表示以第i个坑结尾的,连续j个坑放了,是指以i为结尾,往前连续j个
// int n , m;
// int main()
// {
// scanf(“%d%d”, &n, &m);
// f[0][0] = 1; //什么都不放就是一种策略
// for(int i = 1; i <= n; i)
// {
// for(int j = 0; j < m; j)
// {
// if(j == 0) //第i个坑没放,那么第i-1坑可以是0到m-1所有情况
// {
// for(int k = 0; k < m; k++)
// f[i][j] += f[i-1][k];
// }
// else f[i][j] = f[i-1][j-1];
// }
// }
// LL ans = 0; //所有以第n个结尾的和
// for(int i = 0; i < m; i++)
// {
// ans += f[n][i];
// }
// printf(“%lld”, ans);
// return 0;
// }
// - 当i < m
时:在这种情况下,由于i
小于M
,所以不可能发生爆炸。因此,每增加一个坑,方案数都会翻倍(每个坑都可以选择放置或不放置核物质)。这就是a[i] = 2 * a[i-1]
的逻辑。
// - 当i == m
时:当坑的数量正好等于M
时,除了所有之前的方案翻倍外(每个新坑可以选择放或不放),唯一不被允许的是所有M
个坑都放置了核物质的情况。因此,需要从总数中减去这一种情况,即a[i] = 2 * a[i-1] - 1
。
// - 当i > m
时:对于超过M
个坑的情况,每增加一个坑,原则上方案数仍然翻倍。但是,需要排除新增的坑使得最后连续M
个坑都放置了核物质的情况。这些被排除的方案实际上等同于在第i-M
个坑之前的所有合法方案数(因为第i-M
个坑之后连续放置了M
个核物质),也就是a[i-M-1]
。因此,更新的方程变为a[i] = 2 * a[i-1] - a[i-M-1]
。
include [HTML_REMOVED]
include [HTML_REMOVED]
include [HTML_REMOVED]
using namespace std;
int a[55];
int main()
{
int n, m;
cin >> n >> m;
a[0] = 1;
for(int i = 1; i <= n; i++)
{
if(i < m) a[i] = 2a[i-1];
else if(i == m) a[i] = 2a[i-1] - 1;
else if(i > m) a[i] = 2*a[i-1] - a[i-m-1]; //i-m的那个包是没放
}
cout << a[n];
return 0;
}