zoukankan      html  css  js  c++  java
  • [SDOI2016]储能表——数位DP

    挺隐蔽的数位DP。少见

    其实减到0不减了挺难处理。。。。。然后就懵了。

    其实换个思路:

    xor小于k的哪些都没了,

    只要留下(i^j)大于等于k的那些数的和以及个数,

    和-个数*k就是答案

    数位DP即可

    f[i][0/1][0/1][0/1]表示,前i位,对n,m,k有无限制<=n,<=m,>=k?,xor值的总和

    g[i][0/1][0/1][0/1]表示,前i位,对n,m,k有无限制<=n,<=m,>=k?,合法的方案数

    然后枚举这一位的n,m数位填什么转移

    注意爆int和爆long long:
    1.1<<p爆int,这个还很大,必须立刻取模

    2.最后tmp*k爆long long,k先对p取模

    不稳啊~~

    #include<bits/stdc++.h>
    #define reg register int
    #define il inline
    #define int long long
    #define numb (ch^'0')
    using namespace std;
    typedef long long ll;
    il void rd(ll &x){
        char ch;x=0;bool fl=false;
        while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true);
        for(x=numb;isdigit(ch=getchar());x=x*10+numb);
        (fl==true)&&(x=-x);
    }
    namespace Miracle{
    const int N=66;
    ll n,m,k;
    ll mod;
    ll f[N][2][2][2];
    ll g[N][2][2][2];
    int main(){    
        int t;
        rd(t);
        while(t--){
            scanf("%lld%lld%lld%lld",&n,&m,&k,&mod);
            --n;--m;
            memset(g,0,sizeof g);memset(f,0,sizeof f);
            g[61][1][1][1]=1;        
            for(reg p=60;p>=0;--p){
                int nn=(n>>p)&1LL,nm=(m>>p)&1LL,nk=(k>>p)&1LL;
            //    cout<<" wei "<<p<<endl;
            //    cout<<nn<<" "<<nm<<" "<<nk<<endl;
                for(reg i=0;i<=1;++i){//i
                    for(reg j=0;j<=1;++j){//j
                        for(reg l=0;l<=1;++l){//lim n
                            for(reg r=0;r<=1;++r){//lim m
                                for(reg o=0;o<=1;++o){//lim k
                                    if((l&&i>nn)||(r&&j>nm)||(o&&((i^j)<nk))) continue;
                                    (f[p][((!l)||(i<nn))?0:1][((!r)||(j<nm))?0:1][((!o)||((i^j)>nk))?0:1]+=(f[p+1][l][r][o]+(ll)(i^j)*(1LL*1<<p)%mod*g[p+1][l][r][o]%mod)%mod)%=mod;
                                    (g[p][((!l)||(i<nn))?0:1][((!r)||(j<nm))?0:1][((!o)||((i^j)>nk))?0:1]+=(g[p+1][l][r][o]))%=mod;
                                }
                            }
                        }
                    }
                }
            }
            ll ans=0;
            ll tmp=0;
            for(reg l=0;l<=1;++l){//lim n
                for(reg r=0;r<=1;++r){//lim m
                    for(reg o=0;o<=1;++o){//lim k
                        (ans+=f[0][l][r][o])%=mod;
                        (tmp+=g[0][l][r][o])%=mod;    
                    }
                }
            }
            k%=mod;
            ans=(ans%mod-tmp%mod*k%mod+mod)%mod;
            printf("%lld
    ",ans%mod);
        }
        return 0;
    }
    
    }
    signed main(){
        Miracle::main();
        return 0;
    }
    
    /*
       Author: *Miracle*
       Date: 2019/2/26 18:48:55
    */

    如果想到统计<=k的和和个数的话,就是一个限制比较多(维度多)的数位DP罢了。

  • 相关阅读:
    Redis入门到高可用(十九)——Redis Sentinel
    Redis入门到高可用(十八)—— 主从复制
    动态代理
    Redis入门到高可用(十七)—— 持久化开发运维常见问题
    Redis入门到高可用(十六)—— 持久化
    mybatis批量操作
    Redis入门到高可用(十五)—— GEO
    Redis入门到高可用(十五)—— HyperLogLog
    Redis入门到高可用(十四)—— bitmap
    Redis入门到高可用(十三)—— 发布订阅
  • 原文地址:https://www.cnblogs.com/Miracevin/p/10439639.html
Copyright © 2011-2022 走看看