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;
    }
    
  • 相关阅读:
    [Swift]LeetCode1099. 小于 K 的两数之和 | Two Sum Less Than K
    转 用好HugePage,告别Linux性能故障
    子shell
    转 【推荐】 RAC 性能优化全攻略与经典案例剖析
    转 shell模拟数据库的读写
    c 语言写的高级Oracle&#174;数据库调优及监控工具
    crontab 在unix 没有执行。
    Oracle 云计算
    aix 推荐使用重启
    linux 打开FTP 功能
  • 原文地址:https://www.cnblogs.com/acerkoo/p/10928086.html
Copyright © 2011-2022 走看看