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

    国际惯例的题面:

    听说这题的正解是找什么规律,数位DP是暴力......
    好的,我就写暴力了QAQ。
    我们令f[i][la][lb][lc]表示二进制从高到低考虑位数为i(最低位为1),是否顶n上界,是否顶m上界,是否顶k下界的数字和,g[i][la][lb][lc]表示(同上定义)的数字个数。
    转移的话,先计算出这一位n,m,k的限制,然后枚举这一位第一个数和第二个数填什么,判定xor和是否满足k的条件,转移即可。
    记忆化搜索实现较为简单。
    注意最后计算答案的时候,方案数乘以k可能爆long long,所以k要先取模。

    代码:
    (就算我WA了,TLE了,代码写的像屎一样,也不include<iostream>!pair真好用。)

     1 #include<cstdio>
     2 #include<algorithm> 
     3 #include<cstring>
     4 typedef long long int lli;
     5 const int maxn=1e2+1e1;
     6 
     7 lli f[maxn][2][2][2],g[maxn][2][2][2]; // f is sum , g is count .
     8 int ba[maxn],bb[maxn],bc[maxn],mod;
     9 
    10 inline void dfs(int bit,int la,int lb,int lc) { // bit is the bit that we are determining in range [1,64] .
    11     if( ~f[bit][la][lb][lc] ) return;
    12     if( !bit ) {
    13         f[bit][la][lb][lc] = 0 , g[bit][la][lb][lc] = 1;
    14         return;
    15     } int lima = !la || ba[bit] , limb = !lb || bb[bit] , limc = lc && bc[bit];
    16     f[bit][la][lb][lc] = g[bit][la][lb][lc] = 0;
    17     for(int i=0;i<=lima;i++) for(int j=0;j<=limb;j++) if( ( i ^ j ) >= limc ) {
    18         int ta = la&&i==lima , tb = lb&&j==limb , tc = lc&&(i^j)==limc;
    19         dfs(bit-1,ta,tb,tc);
    20         g[bit][la][lb][lc] = ( g[bit][la][lb][lc] + g[bit-1][ta][tb][tc] ) % mod ,
    21         f[bit][la][lb][lc] = ( f[bit][la][lb][lc] + f[bit-1][ta][tb][tc] + ( (lli) ( i ^ j ) << ( bit -  1 ) ) % mod * g[bit-1][ta][tb][tc] % mod ) % mod;
    22     }
    23 }
    24 
    25 inline int cutbit(lli t,int* dst) {
    26     int ret = 0; memset(dst,0,sizeof(int)*maxn);
    27     while(t) dst[++ret] = t & 1 , t >>= 1;
    28     return ret;
    29 }
    30 
    31 int main() {
    32     static int T,mx;
    33     static lli n,m,k,ans;
    34     scanf("%d",&T);
    35     while(T--) {
    36         scanf("%lld%lld%lld%d",&n,&m,&k,&mod) , --n , --m , memset(f,-1,sizeof(f)) , memset(g,0,sizeof(g)) , mx = std::max( cutbit(k,bc) , std::max( cutbit(n,ba) , cutbit(m,bb) ) ) ,
    37         dfs(mx,1,1,1) , ans = (f[mx][1][1][1]-g[mx][1][1][1]*(k%mod)%mod+mod)%mod , printf("%lld
    ",ans);
    38     }
    39     return 0;
    40 }
    View Code



    く遠く続いてる 空
    遥远地 遥远地 无尽延伸的天空
    その向こうで 君は 何想う
    彼方的你 现在正想些什么
    いつか消える あの星の下
    在那颗终会陨落的星星下
    永遠(とわ)を願い 想い見上げ
    翘首仰望着 祈求着永恒

    強く弱く光を放つ
    灿烂的 黯淡的 明灭闪耀的星光
    君の近くに 北斗七星
    在你身边的 北斗七星
    そんな 輝きであるように
    我想像它一样照耀着你
    君を想い 願い掛けて
    思念着你 许下了愿望

  • 相关阅读:
    JavaScript引用类型
    Java08_方法
    网络爬虫(一)
    openCV(四)——鼠标绘制
    openCV(三)——视频
    openCV(二)——基础绘制函数
    openCV(一) 读取保存图像
    JAVA07-数组
    JAVA06-while循环,do while循环
    JAVA05-switch多重选择
  • 原文地址:https://www.cnblogs.com/Cmd2001/p/8988190.html
Copyright © 2011-2022 走看看