【Atcoder】ARC107 D

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
",dfs(n,k)%mod);
    return 0;
}
原文地址:https://www.cnblogs.com/valk3/p/14095834.html