【Atcoder】ARC107 D - Number of Multisets 记忆化搜索
题目大意
给出 \(n\) 和 \(k\) ,问 \(n\) 个数字的和为 \(k\) 的方案数有多少。
数字可以取\({1,\frac{1}{2},\frac{1}{4},\frac{1}{8},\frac{1}{16},....}\)
题解
考虑两种方案,第一种不取 \(1\) ,第二种取 \(1\)。
\(dp[n][k]\) 表示 \(n\) 个数字组成 \(k\) 的方案。
当不取 \(1\) 的时候,可以取的区间为 \({\frac{1}{2},\frac{1}{4},\frac{1}{8},\frac{1}{16},....}\),乘上一个 \(2\),方案数即 \(dp[n][2*k]\)。
当取 \(1\) 的时候,问题转化为:\(dp[n-1][k-1]\)
我们得到转移方程 \(dp[n][k]=dp[n-1][k-1]+dp[n][k*2]\)
记忆化搜索。
代码
//#include<bits/stdc++.h>
#include <algorithm>
#include <iostream>
#include <map>
#include <set>
#include <stack>
#include <stdio.h>
#include <string.h>
#include <vector>
using namespace std;
#define pb push_back
typedef long long ll;
typedef unsigned long long ull;
const int inf = 0x3f3f3f3f;
const int mod = 998244353;
const int seed = 233;
const int N = 1e7 + 10;
int dp[3010][3010];
int dfs(int n,int k)
{
if(n<k) return 0;
if(dp[n][k]!=-1) return dp[n][k];
if(n==k) return dp[n][k]=1;
if(k==0) return 0;
return dp[n][k]=dfs(n-1,k-1)%mod+dfs(n,2*k)%mod;
}
int main()
{
memset(dp,-1,sizeof(dp));
int n,k;
scanf("%d%d",&n,&k);
printf("%d\n",dfs(n,k)%mod);
return 0;
}