431C. k-Tree

题意

有三个正整数 n , k , d n,k,d n,k,d,总共执行 k k k轮,每一轮可以选择 1   k 1~k 1 k里的任意一个数字,求最后一轮时,数字之和为n且存在一个数字大于d的情况。

解析

简单的dp,最终一个数字大于d是从0个数字大于0转移而来,因此建立两个数组进行转移即可。
状态转移方程
a [ i ] = a [ i ] + a [ i − j ] ( 1 < = j < = m i n ( i , k ) ) a[i]=a[i]+a[i-j] (1<=j<=min(i,k)) a[i]=a[i]+a[ij](1<=j<=min(i,k))
b [ i ] = b [ i ] + a [ i − j ] + b [ i − j ] ( j > = d , 1 < = j < = m i n ( i , k ) ) b[i]=b[i]+a[i-j]+b[i-j] ( j>=d , 1<=j<=min(i,k)) b[i]=b[i]+a[ij]+b[ij](j>=d,1<=j<=min(i,k))

代码

#include<bits/stdc++.h>
using  namespace  std;
typedef long long ll;
const int mod=1e9+7;
// 总和是n,至少有一条边大于等于d,k-tree
int a[105];//不符合条件的
int b[105];
void solve(){
    ll n,k,d ;
    scanf("%lld%lld%lld",&n,&k,&d);
    a[0]=1;
    for(int i=1;i<=n;i++){
        //选择k个 i-j
        for(int j=1;j<=i && j<=k;j++){
            b[i]+=b[i-j];
            b[i]%=mod;
            if(j<d){
                a[i]+=a[i-j];
                a[i]%=mod;
            }
            else{
                b[i]+=a[i-j];
                b[i]%=mod;
            }
        }
    }
    cout<<b[n]<<endl;
}
int main(){
    int t ;
    t=1;
    while(t--){
        solve();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值