首页 > 其他分享 >NOI模拟 UTF-8

NOI模拟 UTF-8

时间:2024-05-28 16:14:08浏览次数:10  
标签:UTF NOI int res checkch && FOLLOW type 模拟

涉及知识点:数位DP

前言

其实这题也没啥好写的,就是好久没做大模拟调代码把人调废了,警醒一下自己……

题意

大模拟,不给简化题意了

\(n\leq 10^5\)。

思路

大递推 DP 里面套小数位 DP,挺恶心的。

设 \(f_i\) 为以第 \(i\) 字节结尾的方案数,每次考虑用 \(4\) 个字节存并且是以 \(i\) 结尾的数,然后 \(3\) 个字节、\(2\) 个字节……判断合法然后转移即可。

代码

用了个 class 来维护,比复制粘贴四次记搜好看多了。

#include<bits/stdc++.h>
#define add(a,b) a=((a)+(b))%P
#define checkch(x,c) (s[id][x]==c || s[id][x]=='?')
using namespace std;
typedef long long LL;
const LL P=1e9+7;
const int MAXN=1e5+5,FOLLOW=1,HEAD1=2,HEAD2=4,HEAD3=8,HEAD4=16;
int n,type[MAXN];
string s[MAXN];
LL ans=0,f[MAXN];
inline int checktype(const int& id){
    int res=0;
    if(checkch(0,'1') && checkch(1,'0')) res|=FOLLOW;
    if(checkch(0,'0')) res|=HEAD1;
    if(checkch(0,'1') && checkch(1,'1') && checkch(2,'0')) res|=HEAD2;
    if(checkch(0,'1') && checkch(1,'1') && checkch(2,'1') && checkch(3,'0')) res|=HEAD3;
    if(checkch(0,'1') && checkch(1,'1') && checkch(2,'1') && checkch(3,'1') && checkch(4,'0')) res|=HEAD4;
    if(!res){
        // cout<<s[id]<<endl;
        cout<<0<<endl;
        exit(0);
    }
    return res;
}
class DigitDP{
    private:
        int len;
        LL g[20][2][2];
        string str,lstr,rstr;
    public:
        DigitDP(int _len,string _lstr,string _rstr){
            len=_len;
            lstr=_lstr;
            rstr=_rstr;
        }
        inline void reset(string _str){
            memset(g,-1,sizeof(g));
            str=_str;
        }
        LL dfs(int dep=0,bool liml=true,bool limr=true){
            if(g[dep][liml][limr]!=-1) return g[dep][liml][limr];
            if(dep>=len){
                return g[dep][liml][limr]=1;
            }
            LL res=0;
            if(str[dep]=='?'){
                for(int dig=(liml?(lstr[dep]-'0'):0);dig<=(limr?(rstr[dep]-'0'):1);dig++){
                    add(res,dfs(dep+1,liml&&(dig==lstr[dep]-'0'),limr&&(dig==rstr[dep]-'0')));
                }
            }
            else if(str[dep]=='1'){
                if((!limr) || (rstr[dep]=='1'))
                    add(res,dfs(dep+1,liml&&('1'==lstr[dep]),limr&&('1'==rstr[dep])));
            }
            else{
                if((!liml) || (lstr[dep]=='0'))
                    add(res,dfs(dep+1,liml&&('0'==lstr[dep]),limr&&('0'==rstr[dep])));
            }
            return g[dep][liml][limr]=res;
        }
}
dp8 (8, "00000001","11111111"),
dp11(11,"00010000000","11111111111"),
dp16(16,"0000100000000000","1111111111111111"),
dp18(18,"010000000000000000","110001001101001111");
int main(){
    // freopen("utf.in","r",stdin);
    // freopen("utf.out","w",stdout);

    ios::sync_with_stdio(false);
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>s[i];
        type[i]=checktype(i);
        // cout<<i<<' ';
        // if(type[i]&FOLLOW) cout<<"FOLLOW"<<' ';
        // if(type[i]&HEAD1) cout<<"HEAD1"<<' ';
        // if(type[i]&HEAD2) cout<<"HEAD2"<<' ';
        // if(type[i]&HEAD3) cout<<"HEAD3"<<' ';
        // if(type[i]&HEAD4) cout<<"HEAD4"<<' ';
        // cout<<endl;
    }
    f[0]=1;
    for(int i=1;i<=n;i++){
        if(i>=1 && (type[i]&HEAD1)){
            string tmp;
            for(int j=1;j<=7;j++) tmp+=s[i][j];
            dp8.reset(tmp);
            add(f[i],f[i-1]*dp8.dfs()%P);
        }
        if(i>=2 && (type[i-1]&HEAD2) && (type[i]&FOLLOW)){
            string tmp;
            for(int j=3;j<=7;j++) tmp+=s[i-1][j];
            for(int j=2;j<=7;j++) tmp+=s[i][j];
            dp11.reset(tmp);
            add(f[i],f[i-2]*dp11.dfs()%P);
        }
        if(i>=3 && (type[i-2]&HEAD3) && (type[i-1]&FOLLOW) && (type[i]&FOLLOW)){
            string tmp;
            for(int j=4;j<=7;j++) tmp+=s[i-2][j];
            for(int j=2;j<=7;j++) tmp+=s[i-1][j];
            for(int j=2;j<=7;j++) tmp+=s[i][j];
            dp16.reset(tmp);
            add(f[i],f[i-3]*dp16.dfs()%P);
        }
        if(i>=4 && (type[i-3]&HEAD4) && (type[i-2]&FOLLOW) && (type[i-1]&FOLLOW) && (type[i]&FOLLOW)){
            bool flag=1;
            for(int j=5;j<=7 && flag;j++)// 四个字节的情况虽然只有后18位有效,但是还是需要判断第一个字节的后三位是否为0
                if(s[i-3][j]=='1') flag=0;
            if(flag){
                string tmp;
                for(int j=2;j<=7;j++) tmp+=s[i-2][j];
                for(int j=2;j<=7;j++) tmp+=s[i-1][j];
                for(int j=2;j<=7;j++) tmp+=s[i][j];
                dp18.reset(tmp);
                add(f[i],f[i-4]*dp18.dfs()%P);
            }
        }
    }
    cout<<f[n]<<endl;
    return 0;
}

标签:UTF,NOI,int,res,checkch,&&,FOLLOW,type,模拟
From: https://www.cnblogs.com/SkyNet-PKN/p/18218221

相关文章

  • CSP历年复赛题-P1190 [NOIP2010 普及组] 接水问题
    原题链接:https://www.luogu.com.cn/problem/P1190题意解读:n个人在m个水龙头排队接水,每个人接水量不同,接完水的排队的人可以接上,求总的接水时间。解题思路:1、先把前m个人安排在m个水龙头2、对于m后面的每一个人,都排在目前m个水龙头总接水时间最短的后面3、最后看m个水龙头最大......
  • 【SCAU操作系统】实验二页面置换算法的模拟实现及命中率对比python源代码及实验报告参
    一、课程设计目的通过请求页式管理方式中页面置换算法的模拟设计,了解虚拟存储技术的特点,掌握请求页式存储管理中的页面置换算法。二、课程设计内容模拟实现OPT(最佳置换)、FIFO和LRU算法,并计算缺页率。三、要求及提示1、首先用随机数生成函数......
  • CSP历年复赛题-P1179 [NOIP2010 普及组] 数字统计
    原题链接:https://www.luogu.com.cn/problem/P1179题意解读:统计l~r之间的整数包括多少个数字2。解题思路:枚举每一个数,对每一个数的每一位数字进行判断。100分代码:#include<bits/stdc++.h>usingnamespacestd;intl,r,ans;intmain(){cin>>l>>r;f......
  • CSP历年复赛题-P1058 [NOIP2008 普及组] 立体图
    原题链接:https://www.luogu.com.cn/problem/P1058题意解读:在m*n的平面上,输出若干个立方体,每一个格子可以有高度不同的多个立方体。解题思路:此题咋一看来,无从下手,仔细分析,其实一道模拟题。如何模拟?我们一起来解决一下几个关键问题:1、如何画图?要在平面上输出图案,本质上就是将......
  • CSP历年复赛题-P1067 [NOIP2009 普及组] 多项式输出
    原题链接:https://www.luogu.com.cn/problem/P1067题意解读:模拟法依次输出多项式内容即可,但是需要考虑的周全,主要有以下关键点:1、系数为0时不输出多项式2、第一个符号,只有负号才输出3、次数不为0时,不输出为1的系数;次数为0时,输出所有系数4、次数为1时,不输出次数;次数为0时不输......
  • 打卡信奥刷题(22)用Scratch图形化工具信奥P1015 [NOIP1999 普及组] 回文数,写了一个好用
    P1015[NOIP1999普及组]回文数,用Scratch实现计算回文数,还写了一个比较好用的反序积木题目[NOIP1999普及组]回文数题目描述若一个数(首位不为零)从左向右读与从右向左读都一样,我们就将其称之为回文数。例如:给定一个十进制数......
  • python探索时钟模拟之旅:从设计到实现
      新书上架~......
  • C++ ─── string的模拟实现
            本博客将简单实现来模拟实现string类,最主要是实现string类的构造、拷贝构造、赋值运算符重载以及析构函数。    下期我们继续讲解完整版string的模拟实现(将不再会是浅拷贝了)        说明:下述string类没有显式定义其拷贝构造函数与赋值运......
  • 赛克oj 1540 开心消消乐(并查集、模拟、回溯)
    赛氪OJ-专注于算法竞赛的在线评测系统(saikr.com)题目描述近来,小明的班上风靡着一款名为“开心消消乐”的游戏,为了成为大家眼中的超人,小明开始疯狂研究这款游戏的玩法。游戏的场景是一个......
  • [NOIP2001 提高组] 一元三次方程求解
    题目描述形如: 这样的一个一元三次方程。给出该方程中各项的系数(......