zoukankan      html  css  js  c++  java
  • bzoj 4693 雪中送温暖

    好题。

    一眼看上去就是数位$dp$。然后我就在想是否是红色一定有什么条件。

    之后发现保证了前驱红色个数的奇偶性,然后我就想是不是红色个数的奇偶决定的。

    分析了一发感觉非常有理,但是后来我发现如果是个数的话我没有加上自己,然后这个思路就被我扔了。

    然后就没思路了。。。。

    看了题解真的觉得自己迟钝到一定地步了。

    颜色取决于$(1,1......,1)$到这个点的路径条数(虽然很好证,但是怎么想到才是关键啊)。

    然后就很简单了。

    条件就是$forall xi|xj==xi+xj$,即没有交集($lucas$定理)。

    然后就可以数位$dp$了。

    $O(T*3^k*k*logw)$。

    #include <bits/stdc++.h>
    #define for1(a,b,i) for(int i=a;i<=b;++i)
    #define FOR2(a,b,i) for(int i=a;i>=b;--i)
    using namespace std;
    typedef long long ll;
     
    #define M 20
    #define N 520
    #define mod 998244353
    int n;
    ll L[M],R[M];
     
    inline void inc(int &x,int y) {x+=y,x-=x>=mod?mod:0;}
     
    struct set_ {
        int id[N][N];
        int size,ax[N*N],ay[N*N],f[N*N];
         
        inline void clear() {
            for1(1,size,i) {
                f[i]=0;
                id[ax[i]][ay[i]]=0;
            }
            size=0;
        }
        inline void add_(int x,int y,int z) {
            if(!id[x][y]) {
                id[x][y]=++size;
                ax[size]=x,ay[size]=y;
            }
            inc(f[id[x][y]],z);
        }
    }Y[2];
     
    inline void turn_(int be,int &x,int &y,int z) {
        if(z&&!(y>>z-1&1)&&!(R[z]>>be&1)) return x=-1,void();
        for1(1,n,i) if(z!=i&&!(x>>i-1&1)&&(L[i]>>be&1)) return x=-1,void();
        if(z&&!(x>>z-1&1)&&!(L[z]>>be&1)) x+=1<<z-1;
        for1(1,n,i) if(z!=i&&!(y>>i-1&1)&&(R[i]>>be&1)) y+=1<<i-1;
    }
     
    int main () {
        //freopen("a.in","r",stdin);
        int Test_;
        scanf("%d",&Test_);
        while (Test_--) {
            scanf("%d",&n);
            for1(1,n,i) scanf("%lld",L+i),--L[i];
            for1(1,n,i) scanf("%lld",R+i),--R[i];
             
            int opt=0;
            Y[0].add_(0,0,1);
             
            FOR2(49,0,i) {
                FOR2(Y[opt].size,1,j) {
                    int x=Y[opt].ax[j];
                    int y=Y[opt].ay[j];
                    int sel=Y[opt].f[j];
                    for1(0,n,k) {
                        int ax=x,ay=y;
                        turn_(i,ax,ay,k);
                        if(ax==-1) continue;
                        Y[opt^1].add_(ax,ay,sel);
                    }
                }
                Y[opt].clear();
                opt^=1;
            }
            int ans=0;
            for1(1,Y[opt].size,i) inc(ans,Y[opt].f[i]);
            Y[opt].clear();
            printf("%d
    ",ans);
        }
    }
    View Code
  • 相关阅读:
    06-图3 六度空间
    06-图2 Saving James Bond
    06-图1 列出连通集
    05-树9 Huffman Codes
    数据结构学习笔记04树(堆 哈夫曼树 并查集)
    05-树8 File Transfer
    05-树7 堆中的路径
    十天学会单片机Day1点亮数码管(数码管、外部中断、定时器中断)
    设计模式—— 四:接口隔离原则
    设计模式—— 一:单一职责原则
  • 原文地址:https://www.cnblogs.com/asd123www/p/9768592.html
Copyright © 2011-2022 走看看