1. 程式人生 > >bzoj 4693 雪中送溫暖

bzoj 4693 雪中送溫暖

all %d scanf ear con std bits truct inline

好題。

一眼看上去就是數位$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); } }

bzoj 4693 雪中送溫暖