「专题训练」k-Tree(CodeForces Round #247 Div.2 C)
Posted samhx
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了「专题训练」k-Tree(CodeForces Round #247 Div.2 C)相关的知识,希望对你有一定的参考价值。
题意与分析(Codeforces-431C)
题意是这样的:给出K-Tree——一个无限增长的树,它的每个结点都恰有(K)个孩子,每个节点到它(K)个孩子的(K)条边的权重各为(1,2,...,K),问现有多少条路径,使从根节点出发到某个结点所经过的边权重之和恰为n,且经过的边至少有一条权重不小于(d)。
我们来考虑一下阶段:一层一层的走下去——这个是显然的。而状态是什么?影响我们答案(路径条数)的只有一个,权重的和,它是由我们底下的若干个孩子所走的权重和的情况的和构成的。从某个节点走到某个节点改变了什么?当我走了一条边i,我就还剩(n-i)的权重需要走了。而我有(k)个边,因此对于一个K-Tree的某个点(每个点是等价的,所以决定性因素只能是和),如果它还剩(n)的权重和没有走,那么它的状态转移方程就是(dp[n-1]+dp[n-2]+...+dp[n-k]=dp[n])。这样就能求出没有限制条件下的路径个数。
然后考虑一下限制条件。不小于(d),很自然地会觉得有点困难去实现。于是想到正难则反,我们求出所有边权重小于d的情况就行了——也就是(k=d-1)。而同样的,不改变的是预先的权重和(n),因此再次运用上面的状态转移方程,然后把(k)代入为(d-1)即可。二者最后相减即可。
代码
注意减法操作时候的取模。
#include <bits/stdc++.h>
using namespace std;
const long long mod=1e9+7;
long long dpa[105], dpb[105];
int main()
{
int n,k,d; cin>>n>>k>>d;
dpa[0]=dpb[0]=1;
for(int i=1;i<=n;++i)
{
for(int j=1; j<=k && i-j>=0; ++j)
{
dpa[i]=(dpa[i]+dpa[i-j])%mod;
}
}
for(int i=1;i<=n;++i)
{
for(int j=1; j<=d-1 && i-j>=0; ++j)
{
dpb[i]=(dpb[i]+dpb[i-j])%mod;
}
}
cout<<(dpa[n]-dpb[n]+mod)%mod<<endl;
return 0;
}
以上是关于「专题训练」k-Tree(CodeForces Round #247 Div.2 C)的主要内容,如果未能解决你的问题,请参考以下文章