zoukankan      html  css  js  c++  java
  • 4513: [Sdoi2016]储能表

    4513: [Sdoi2016]储能表

    链接

    分析:

      数位dp。

      横坐标和纵坐标一起数位dp,分别记录当前横纵坐标中这一位是否受n或m的限制,在记录一维表示当前是否已经大于k了。

      然后需要两个数组记录答案,分别记录个数和答案的和。

      语意不清了。。。看代码吧。。

    代码:

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<iostream>
    #include<cctype>
    #include<set>
    #include<vector>
    #include<queue>
    #include<map>
    #define fi(s) freopen(s,"r",stdin);
    #define fo(s) freopen(s,"w",stdout);
    using namespace std;
    typedef long long LL;
    
    inline LL read() {
        LL x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
        for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f;
    }
    
    const int N = 1005;
    int a[N], b[N], c[N], c1, c2, c3, Cnt;
    LL dp[N][2][2][2], mi[N], cnt[N][2][2][2], n, m, k, p;
    #define pa pair<LL,LL>
    
    pa dfs(int x,LL now,bool l1,bool l2,bool l3) {
        if (!x) { return pa((-k + p) % p, 1); }
        if (dp[x][l3][l1][l2]) return pa(dp[x][l3][l1][l2], cnt[x][l3][l1][l2]);
        int u1 = l1 ? a[x] : 1;
        int u2 = l2 ? b[x] : 1;
        LL res = 0, sum = 0;
        for (int i = 0; i <= u1; ++i) 
            for (int j = 0; j <= u2; ++j) {
                int t = i ^ j;
                if (l3 && t < c[x]) continue;
                pa tmp = dfs(x - 1, t ? now + mi[x - 1] : now, l1 && i == u1, l2 && j == u2, l3 && t == c[x]);
                res += (tmp.first + tmp.second * t * mi[x - 1] % p) % p;
                sum += tmp.second;
                res %= p;
                sum %= p;
            }
        dp[x][l3][l1][l2]= res, cnt[x][l3][l1][l2] = sum;
        return pa(res, sum);
    }
    void Calc() {
        n --, m --;
        c1 = c2 = c3 = Cnt = 0;
        LL t = n; 
        while (t) a[++c1] = t % 2, t /= 2;
        t = m; 
        while (t) b[++c2] = t % 2, t /= 2;
        t = k;
        while (t) c[++c3] = t % 2, t /= 2;
        Cnt = max(c1, max(c2, c3));
        cout << dfs(Cnt, 0, 1, 1, 1).first << "
    ";
        for (int i = 0; i <= Cnt; ++i) a[i] = b[i] = c[i] = 0;
        memset(dp, 0, sizeof(dp));
        memset(cnt, 0, sizeof(cnt));
    }
    void solve() {
        n = read(), m = read(), k = read(), p = read();
        mi[0] = 1;
        for (int i = 1; i <= 100; ++i) mi[i] = mi[i - 1] * 2 % p;
        Calc();
    }
    int main() {
        for (int T = read(); T --; solve());    
        return 0;
    }
  • 相关阅读:
    1058 A+B in Hogwarts (20)
    1046 Shortest Distance (20)
    1061 Dating (20)
    1041 Be Unique (20)
    1015 Reversible Primes (20)(20 分)
    pat 1027 Colors in Mars (20)
    PAT 1008 Elevator (20)
    操作系统 死锁
    Ajax的get方式传值 避免& 与= 号
    让IE浏览器支持CSS3表现
  • 原文地址:https://www.cnblogs.com/mjtcn/p/10392337.html
Copyright © 2011-2022 走看看