Find a car题解

Find a car题解

恶心题。
题目链接
首先规律就难以发现:
\(a[i][j]=(i-1)\)^\((j-1)+1 \sum_{i=1}^{x} \sum_{j=1}^{y} (a[i][j]<=k)\)
然后神奇数位DP,每一位枚举这一位是0,是1,是否满足i、j、k 的限制,(1为不满足,0为满足。)

#include<bits/stdc++.h>
#define ll long long
#define work(x,y,z) if(i>1||w==x) dfs2(i>>1,state,y,z,i>1?w^x:w)
using namespace std;
const ll mod=1e9+7;
int t,t1,t2,t3,t4,k;
ll q,fs[12],fc[12],gs[12],gc[12];
inline void add(ll &x){if(x>=mod)x-=mod;}
inline int read(){
   int T=0,F=1; char ch=getchar();
   while(ch<'0'||ch>'9'){if(ch=='-') F=-1; ch=getchar();}
   while(ch>='0'&&ch<='9') T=(T<<3)+(T<<1)+(ch-48),ch=getchar();
   return F*T; 
}
void dfs2(int i,int state,int u,int v,int w){
    if(!i){
      if(w) fs[v]=(fs[v]+q*gc[u])%mod;
      add(fs[v]+=gs[u]); add(fc[v]+=gc[u]);
      return;
    }
    if(i&state){work(0,u,v|i); work(1,u,v);}//有限制,这一位可以选1,可以选0
    else work(0,u,v);//有限制,只能选0
    work(0,u|i,v|i); work(1,u|i,v|i);//无限制,即可以选0,也可以选1
}//搜索这一位选择,满足x,y,z哪些的限制
ll dfs(ll x,ll y,ll z){
   if(x<0||y<0||z<0) return 0;
   ll ans=0;
   memset(gc,0,sizeof(gc)),memset(gs,0,sizeof(gs)),gc[0]=1;
   for(int i=(1<<30);i;i>>=1){
       q=i,dfs2(4,(((x&i)>0)*4)|(((y&i)>0)*2)|((z&i)>0),0,0,0);//每一位的限制
       memcpy(gc,fc,sizeof(fc)),memcpy(gs,fs,sizeof(fs));
       memset(fc,0,sizeof(fc)),memset(fs,0,sizeof(fs));
   }
   for(int i=0;i<8;++i) add(ans+=gc[i]),add(ans+=gs[i]);
   return ans;
}
int main(){
   t=read();
   while(t--){
      t1=read()-2,t2=read()-2,t3=read()-1,t4=read()-1,k=read()-1;
      printf("%lld\n",((dfs(t3,t4,k)-dfs(t1,t4,k)-dfs(t3,t2,k)+dfs(t1,t2,k))%mod+mod)%mod);
   }
   return 0;
}
posted @ 2019-11-11 21:49  lsoi_ljk123  阅读(182)  评论(0编辑  收藏  举报