hdu4906Our happy ending 状压dp

//给出 n , k , l ( n , k <= 20 , l <= 1e9)
//找出长度为n的序列 , 序列的所有数都小于l  , 且序列中可以找出
//一些数 , 其和为k
//状态压缩
//dp[i]  i状态下有多少种情况 , i的二进制数中为1表示序列能组成这个数
//next = (1<<(p-1))|j|((j<<p)&s) ;
//dp[next] += dp[j] ; 
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std ;
const int maxn = (1<<20) ;
typedef long long ll ;
const int mod = 1e9+7 ;
int dp[maxn] ;
int main()
{
    int n , k ,  l;
    int t ;
    scanf("%d"  ,&t) ;
    while(t--)
    {
        scanf("%d%d%d" , &n , &k , &l) ;
        int d = l - k > 0 ? l - k : 0 ;
        int s = (1<<k) - 1 ;
        int m = min(l , k ) ;
        memset(dp , 0 , sizeof(dp)) ;
        dp[0] = 1 ;
        for(int i = 1;i <= n;i++)
        {
            for(int j = s;j >= 0;j--)
            {
                int tmp = dp[j] ;
                if(!tmp)continue ; 
                for(int p = 1;p <= m;p++)
                {
                    int next = (1<<(p-1))|j|((j<<p)&s) ;
                    dp[next] = (tmp + dp[next])%mod ;
                }
                dp[j] = (dp[j] + (ll)tmp*d%mod)%mod ;
            }
        }
        int ans = 0 ;
        for(int i = 0 ;i <= s;i++)
        if(i&(1<<(k-1)))
        ans = (ans + dp[i])%mod ;
        cout<<ans<<endl ;
    }
}

你可能感兴趣的:(hdu4906Our happy ending 状压dp)