zoukankan      html  css  js  c++  java
  • HDU

    HDU - 5330

    感觉这种dp和子集和dp差不多, 有点难想到。

    dp[ i ][ S ][ j ]  表示最低的 i 位和 S最低的 i 位一样的所有串中, 和 S 的距离为 j 的有多少个。

    #pragma GCC optimize(2)
    #pragma GCC optimize(3)
    #pragma GCC optimize(4)
    #include<bits/stdc++.h>
    #define LL long long
    #define LD long double
    #define ull unsigned long long
    #define fi first
    #define se second
    #define mk make_pair
    #define PLL pair<LL, LL>
    #define PLI pair<LL, int>
    #define PII pair<int, int>
    #define SZ(x) ((int)x.size())
    #define ALL(x) (x).begin(), (x).end()
    #define fio ios::sync_with_stdio(false); cin.tie(0);
    
    using namespace std;
    
    const int N = 2e5 + 7;
    const int inf = 0x3f3f3f3f;
    const LL INF = 0x3f3f3f3f3f3f3f3f;
    const int mod = (int)1e9 + 7;
    const double eps = 1e-8;
    const double PI = acos(-1);
    
    template<class T, class S> inline void add(T &a, S b) {a += b; if(a >= mod) a -= mod;}
    template<class T, class S> inline void sub(T &a, S b) {a -= b; if(a < 0) a += mod;}
    template<class T, class S> inline bool chkmax(T &a, S b) {return a < b ? a = b, true : false;}
    template<class T, class S> inline bool chkmin(T &a, S b) {return a > b ? a = b, true : false;}
    
    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
    
    int n, m, up;
    int dp[2][N][23];
    int c[N];
    int (*f)[23] = dp[0];
    int (*g)[23] = dp[1];
    int v[12];
    LL ans[23];
    
    char s[20];
    
    void init() {
        memset(ans, 0, sizeof(ans));
        for(int i = 0; i < up; i++) {
            c[i] = 0;
        }
        for(int i = 0; i < up; i++) {
            for(int j = 0; j <= 2 * m; j++) {
                f[i][j] = 0;
            }
        }
    }
    
    int main() {
        int T; scanf("%d", &T);
        while(T--) {
            scanf("%d%d", &n, &m);
            up = 1;
            for(int i = 1; i <= m; i++) {
                up = up * 3;
            }
            init();
            for(int i = 0; i < n; i++) {
                int val = 0;
                scanf("%s", s);
                for(int j = 0; j < m; j++) {
                    val = val * 3 + (s[j] - '0');
                }
                f[val][0]++;
                c[val]++;
            }
            for(int i = 0; i < m; i++) {
                swap(f, g);
                for(int mask = 0; mask < up; mask++) {
                    for(int j = 0, k = mask; j < m; j++, k /= 3) {
                        v[j] = k % 3;
                    }
                    int pmask0 = 0, pmask1 = 0, pmask2 = 0;
                    for(int j = m - 1; j >= 0; j--) {
                        pmask0 *= 3; pmask1 *= 3; pmask2 *= 3;
                        if(j == i) {
                            pmask0 += 0;
                            pmask1 += 1;
                            pmask2 += 2;
                        } else {
                            pmask0 += v[j];
                            pmask1 += v[j];
                            pmask2 += v[j];
                        }
                    }
                    for(int j = 0; j <= 2 * m; j++) {
                        f[mask][j] = 0;
                        if(v[i] == 0) {
                            f[mask][j] += g[pmask0][j];
                            if(j >= 1) f[mask][j] += g[pmask1][j - 1];
                            if(j >= 2) f[mask][j] += g[pmask2][j - 2];
                        }
                        else if(v[i] == 1) {
                            if(j >= 1) f[mask][j] += g[pmask0][j - 1];
                            f[mask][j] += g[pmask1][j];
                            if(j >= 1) f[mask][j] += g[pmask2][j - 1];
                        }
                        else {
                            if(j >= 2) f[mask][j] += g[pmask0][j - 2];
                            if(j >= 1) f[mask][j] += g[pmask1][j - 1];
                            f[mask][j] += g[pmask2][j];
                        }
                    }
                }
            }
            for(int mask = 0; mask < up; mask++) {
                ans[0] += 1LL * c[mask] * (c[mask] - 1);
                for(int j = 1; j <= 2 * m; j++) {
                    ans[j] += 1LL * c[mask] * f[mask][j];
                }
            }
            for(int i = 0; i <= 2 * m; i++) {
                printf("%lld
    ", ans[i] / 2);
            }
        }
        return 0;
    }
    
    /*
    */
  • 相关阅读:
    【人生】未来一段时间的规划
    java new一个对象的过程中发生了什么
    Openwrt missing dependencies for the following libraries:nf_nat.ko
    Lua日期转秒 时间函数os.time()和日期函数os.date()的使用
    lua 命令行参数
    Robot Framework自动化测试Telnet简单示例使用
    VirtualBox安装OpenWrt虚拟机
    C语言中负数的补码存储(1000 0000 表示128)
    Robot Framework自动化测试SSHLibrary简单示例使用
    dkjson实现lua空table编码为数组[]
  • 原文地址:https://www.cnblogs.com/CJLHY/p/11308629.html
Copyright © 2011-2022 走看看