zoukankan      html  css  js  c++  java
  • Haiku(状压dp)

    题目描述

    对于一个长度问n的数组A,设第i个元素为Ai(0≤i<n)。
    问有多少个长度为n的数组A,满足1≤Ai≤10,且这个数组是诗。
    给定x,y,z,一个长度为n的数组是诗当且仅当存在i,j,k,l(0≤i<j<k<l≤N)使得:

    ai+ai+1+...+aj−1=x。
    aj+aj+1+...+ak−1=y。
    ak+ak+1+...+al−1=z。

    输入

    一行,四个整数,分别表示n x y z

    输出

    输出满足条件的数组数量 mod 109+7。

    样例输入

    3 5 7 5

    样例输出

    1

    hint

    思路

    逆向思考,总数减去不满足条件的数量。
    既然 x+y+z<=17, 则可用二进制表示和为多大,比如:100,可表示3, 1000100可表示6、3、4。
    因为,可以在O(2^17)枚举各种状态的次数,总数减去状态和即为答案。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    const int maxm = 1<<17;
    const int mod = 1e9+7;
    typedef long long ll;
    inline int bit(int x, int mov) { return x|(1<<mov-1); }
    int n, m, x, y, z;
    int vp=0;
    ll ans = 1, dp[42][maxm];
    
    int main() {
       scanf("%d%d%d%d", &n, &x, &y, &z);
       m = 1<<(x+y+z); --m;
       vp = bit(vp, x+y+z), vp = bit(vp, y+z), vp = bit(vp, z);
       dp[0][0] = 1;
       for (int i=1; i<=n; ++i) {
           (ans *= 10) %= mod;
           for (int mask=0; mask<=m; ++mask) {
               if(!dp[i-1][mask]) continue;
               for (int k=1; k<=10; ++k) {
                   int cur = bit(mask<<k, k);
                   cur &= m;
                   if((cur&vp)!=vp)
                       (dp[i][cur] += dp[i-1][mask]) %= mod;
               }
           }
       }
       for (int mask=0; mask<=m; ++mask)
           ans = (ans - dp[n][mask] + mod) % mod;
       printf("%lld
    ", ans);
       return 0;
    }
    
  • 相关阅读:
    Leetcode 191.位1的个数 By Python
    反向传播的推导
    Leetcode 268.缺失数字 By Python
    Leetcode 326.3的幂 By Python
    Leetcode 28.实现strStr() By Python
    Leetcode 7.反转整数 By Python
    Leetcode 125.验证回文串 By Python
    Leetcode 1.两数之和 By Python
    Hdoj 1008.Elevator 题解
    TZOJ 车辆拥挤相互往里走
  • 原文地址:https://www.cnblogs.com/acerkoo/p/10928086.html
Copyright © 2011-2022 走看看