zoukankan      html  css  js  c++  java
  • 【Luogu】P4067储能表(数位DP)

      题目链接

      好的

      看到这题之后我一直在想反演,然后想不出来,一度以为自己脑子有问题

      然后我脑子真的有问题,这题tm根本就不是反演

      设f[i][j][k][l]表示现在已经DP到从高位往低数的第i位,有没有碰到n的上界,有没有碰到m的上界,有没有碰到k的上界

      然后记忆化DFS搞一搞,把方案数和异或和都记录下来,最后减掉输出

      

    #include<cstdio>
    #include<cstring>
    #include<cctype>
    #include<cstdlib>
    #include<algorithm>
    #define maxn 50
    using namespace std;
    inline long long read(){
        long long num=0,f=1;
        char ch=getchar();
        while(!isdigit(ch)){
            if(ch=='-')    f=-1;
            ch=getchar();
        }
        while(isdigit(ch)){
            num=num*10+ch-'0';
            ch=getchar();
        }
        return num*f;
    }
    
    long long n,m,e,mod;
    
    struct Ans{
        long long xum,sum;
    }f[100][2][2][2];
    bool vis[100][2][2][2];
    
    long long Maxi;
    
    void dfs(long long len,long long nown,long long nowm,long long nowk){
        if(len>Maxi){
            f[len][nown][nowm][nowk]=(Ans){0,1};
            return;
        }
        if(vis[len][nown][nowm][nowk])    return;
        Ans &ret=f[len][nown][nowm][nowk];
        vis[len][nown][nowm][nowk]=1;
        long long mn=(n>>(Maxi-len))&1,mm=(m>>(Maxi-len))&1,mk=(e>>(Maxi-len))&1;
        for(long long i=0;i<=(nown?mn:1);++i)
            for(long long j=0;j<=(nowm?mm:1);++j){
                if(nowk&&(i^j)<mk)    continue;
                dfs(len+1,nown&&(i==mn),nowm&&(j==mm),nowk&&((i^j)==mk));
                Ans now=f[len+1][nown&&(i==mn)][nowm&&(j==mm)][nowk&&(i^j)==mk];
                ret.sum=(ret.sum+now.sum)%mod;
                ret.xum=(ret.xum+(1ll<<(Maxi-len))*(i^j)%mod*now.sum+now.xum)%mod;
            }
        return;
    }
    
    
    int main(){
        long long T=read();
        while(T--){
            n=read()-1;m=read()-1;e=read();mod=read();
            memset(vis,0,sizeof(vis));    Maxi=0;
            memset(f,0,sizeof(f));
            long long nn=n,nm=m,ne=e;long long cnt=0;
            while(nn){    cnt++;    nn>>=1;}
            Maxi=max(Maxi,cnt);    cnt=0;
            while(nm){    cnt++;    nm>>=1;}
            Maxi=max(Maxi,cnt);    cnt=0;
            while(ne){    cnt++;    ne>>=1;}
            Maxi=max(Maxi,cnt);
            dfs(1,1,1,1);
            Ans now=f[1][1][1][1];
            long long ans=(now.xum%mod-(e%mod)*now.sum%mod+mod)%mod;
            printf("%lld
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    PHP文件下载
    win7的IE11降到IE8
    京东电话面试——PHP开发
    PHP异常处理
    php错误处理
    php练习7——类的运用(四则运算or面积计算[javascript小技巧——根据需求显示不同界面])
    php练习6——面向对象编程(打印乘法表)
    SICP阅读笔记(一)
    随笔(2015-18-19)
    MIT scheme入门使用
  • 原文地址:https://www.cnblogs.com/cellular-automaton/p/8882531.html
Copyright © 2011-2022 走看看