zoukankan      html  css  js  c++  java
  • bzoj4693: 雪中送温暖

    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
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    标记法
    学习实际经验
    标准项目文档
    项目开发流程规范文档
    未来与人工智能
    正则表达式
    http.pieplining
    二、防火墙
    一、信息安全产品分类
    【metasploit教程】之建立数据库
  • 原文地址:https://www.cnblogs.com/ccz181078/p/7187895.html
Copyright © 2011-2022 走看看