码迷,mamicode.com
首页 > 其他好文 > 详细

bzoj4693: 雪中送温暖

时间:2017-07-16 00:07:06      阅读:188      评论:0      收藏:0      [点我收藏+]

标签:scan   const   output   sizeof   printf   max   return   amp   size   

Description

每年的1月10日是温暖节,在这一天,化身出题人的C_SUNSHINE将会给OIer们送温暖。OIer们只要在门口放上一个
仙人掌,就能在早上的某个时刻听到门外传来一声:“开门,送温暖——”作为一个萌萌哒OIer,Salroey从C_SUN
SHINE那里收到了一个令人感到温暖的问题,她想与你分享分享。有一个K维空间,每个整点上都有一个信号灯,每
个信号灯的位置都可以由K 个整数(x1,x2...xk) 表示,信号灯的颜色定义如下:
1.如果存在i满足xi=0则(x1,x2...xk) 为绿色。
2.如果对于所有i满足xi=1 则 (x1,x2...xk)为红色。
3.对于信号灯(x1,x2...xk) ,定义它的k 个前驱为恰好某一维的坐标比这个信号灯恰好少1
其余坐标都与这个信号灯相等的信号灯,即(x1,x2..xi-1,xi+1...xk) 。如果这些前驱中有偶数个红灯
则这个信号灯为绿色,否则为红色。
现在给定k 和一个k 维矩形,求矩形内部红灯数目,包括边界。

Input

第一行一个正整数t 表示数据组数,对于每组数据:
第一行一个整数k 。
第二行 2k个整数L1,L2..Lk,R1,R2...Rk 描述一个矩形的两个顶点。
T<=10,1<=k<=9,1<=Li<=Ri<=10^15

Output

对于每组数据输出一个整数表示红灯的数目,答案对998244353取模。

打表可知当且仅当 对于每个二进制位,至多有一维坐标为1 时为红色,于是可以从高位到低位进行数位dp,记录每一维坐标已确定部分与Li,Ri的关系($x=L_i || x=R_i || L_i<x<R_i$)

时间复杂度$O(T3^klog(max{R_i}))$

#include<cstdio>
#include<cstring>
typedef long long i64;
const int P=998244353;
int T,n,t;
i64 l[11],r[11];
int pw3[11],ls[11],rs[11],eq[11],peq[11];
int f[55][20007],*f1,*f0;
void inc(int&a,int b){b+=a-P;a=b+(b>>31&P);}
void dfs(int w,int d,int S,int S2){
    if(w==-1)return inc(f0[S2],f1[S]);
    S*=3,S2*=3;
    if(!peq[w]){
        if(!ls[w])dfs(w-1,d,S,S2);
        dfs(w-1,d,S+1,S2+1+rs[w]);
        dfs(w-1,d,S+2,S2+2);
        if(!d){
            dfs(w-1,1,S,S2+(ls[w]^1)*2);
            if(rs[w])dfs(w-1,1,S+1,S2+1);
            dfs(w-1,1,S+2,S2+2);
        }
    }else if(!eq[w]){
        dfs(w-1,d,S,S2);
        if(!d)dfs(w-1,1,S,S2+1);
    }else if(d+rs[w]<=1)dfs(w-1,d+rs[w],S,S2);
}
int main(){
    for(int i=pw3[0]=1;i<10;++i)pw3[i]=pw3[i-1]*3;
    f[51][0]=1;
    for(scanf("%d",&T);T;--T){
        scanf("%d",&n);
        for(int i=0;i<n;++i)scanf("%lld",l+i),--l[i];
        for(int i=0;i<n;++i)scanf("%lld",r+i),--r[i];
        for(t=50;t>=0;--t){
            f1=f[t+1];
            memset(f0=f[t],0,sizeof(int)*pw3[n]);
            for(int i=0;i<n;++i){
                ls[i]=l[i]>>t&1;
                eq[i]=!((l[i]^r[i])>>t);
                peq[i]=!((l[i]^r[i])>>t+1);
                rs[i]=r[i]>>t&1;
            }
            dfs(n-1,0,0,0);
        }
        int ans=0;
        for(int i=0;i<pw3[n];++i)inc(ans,f0[i]);
        printf("%d\n",ans);
    }
    return 0;
}

 

bzoj4693: 雪中送温暖

标签:scan   const   output   sizeof   printf   max   return   amp   size   

原文地址:http://www.cnblogs.com/ccz181078/p/7187895.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!