【LG4067】[SDOI2016]储能表

【LG4067】[SDOI2016]储能表

题面

洛谷

题解

这种$n$、$m$出奇的大的题目一看就是数位$dp$啦

其实就是用一下数位$dp$的套路

设$f[o][n][m][k]$表示当前做到第$i$位卡不卡$n,m,k$的界

其中$f$是个$pair$一维存方案数、一位存数值

然后按照普通套路$dfs$即可

代码

#include <iostream> 
#include <cstdio> 
#include <cstdlib> 
#include <cstring> 
#include <cmath> 
#include <algorithm>
#include <vector> 
using namespace std; 

template <typename T> 
void read(T &x) { 
    int op = 1; x = 0; char ch = getchar(); 
    while (!isdigit(ch)) { if (ch == '-') op = -1; ch = getchar(); } 
    while (isdigit(ch)) x = x * 10 + ch - '0', ch = getchar(); 
    x *= op; 
}
typedef long long ll; 
typedef pair<ll, ll> P; 
ll N, M, K, Mod;
int mx; 
P f[70][2][2][2]; 
bool vis[70][2][2][2]; 
void pls(ll &x, ll y) { x += y; if (x >= Mod) x -= Mod; } 
P dfs(int o, bool n, bool m, bool k) { 
    if (o > mx) return make_pair(1, 0); 
    if (vis[o][n][m][k]) return f[o][n][m][k]; 
    vis[o][n][m][k] = 1;
    int lim_n = n ? ((N >> mx - o) & 1) : 1, lim_m = m ? ((M >> mx - o) & 1) : 1, lim_k = k ? ((K >> mx - o) & 1) : 1; 
    for (int i = 0; i <= lim_n; i++)
        for (int j = 0; j <= lim_m; j++) {
            if (k && lim_k > (i ^ j)) continue; 
            P p = dfs(o + 1, n && (i == lim_n), m && (j == lim_m), k && ((i ^ j) == lim_k)); 
            pls(f[o][n][m][k].first, p.first); 
            pls(f[o][n][m][k].second, ((1ll << mx - o) * (i ^ j) % Mod * p.first % Mod + p.second) % Mod); 
        }
    return f[o][n][m][k]; 
} 
int main () {
    int T; read(T); 
    while (T--) { 
        read(N), read(M), read(K), read(Mod); 
        memset(vis, 0, sizeof(vis)); 
        memset(f, 0, sizeof(f));  
        N--, M--; ll n = N, m = M, k = K; int res = 0; mx = 0; 
        while (n) ++res, n >>= 1ll; mx = max(mx, res), res = 0;   
        while (m) ++res, m >>= 1ll; mx = max(mx, res), res = 0; 
        while (k) ++res, k >>= 1ll; mx = max(mx, res); 
        P ans = dfs(1, 1, 1, 1); 
        printf("%lld\n", (1ll * ans.second - 1ll * K % Mod * ans.first  % Mod + Mod) % Mod); 
    } 
    return 0; 
} 

 

posted @ 2019-01-05 21:24  heyujun  阅读(347)  评论(0编辑  收藏  举报