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\n",ans);
    }
}
View Code

 

posted @ 2018-10-10 19:45  asd123www  阅读(290)  评论(0编辑  收藏  举报