zoukankan      html  css  js  c++  java
  • our happy ending(状压dp)

    题意:给定一个n,k,l。

    问有多少长度为n的序列满足选出一些数使得他们相加为k,数列中每个数都在1-l以内。

    Solution

    正解还是很妙的。

    状压dp,设dp[i][j]表示长度为i的序列,能表示出集合为j的序列个数。

    这个状态非常好,我们每局下一个可填的数,可选集合就变成了j|(1<<p-1)|(j<<p&size)

    Code

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    typedef long long ll;
    const int mod=1e9+7;
    ll dp[1<<20],ans;
    int n,k,l,t,ma;
    int main(){
        scanf("%d",&t);
        while(t--){
            scanf("%d%d%d",&n,&k,&l);
            memset(dp,0,sizeof(dp));
            ma=(1<<k)-1;dp[0]=1;
            for(int i=1;i<=n;++i)
              for(int j=ma;j>=0;--j)if(dp[j]){
                 ll pu=dp[j];
                 for(int p=1;p<=min(k,l);++p) {
                    int x=(1<<p-1)|j|((j<<p)&ma);
                    dp[x]+=pu;
                    if(dp[x]>mod)dp[x]-=mod;
                }
                if(l>k){
                    dp[j]+=(pu*(l-k))%mod;
                    if(dp[j]>mod)dp[j]-=mod;
                }
            }ans=0;
            for(int i=1;i<=ma;++i)if(i&(1<<k-1)){ans+=dp[i];if(ans>mod)ans-=mod;}
            printf("%lld
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    l1-010
    l1-009
    L1-008修改
    l1-008
    Codeforces Round #406 (Div. 2)
    求N!的长度【数学】 51nod 1058 1130
    51nod 1090 & 1267 【二分简单题】
    Codeforces Round #405 (Div. 2)
    Codeforces Round #404 (Div. 2)
    PAT 天梯赛真题集(L2、L3)
  • 原文地址:https://www.cnblogs.com/ZH-comld/p/9682255.html
Copyright © 2011-2022 走看看