题解 Medium Counting
又是神仙DP
发现如果只有两个串就很好做了
于是这个神仙DP定义就从这里下手:令 $dp[p][c][l][r] 表示在 \([s_l, s_r]\) 这段字符串中,考虑从第 \(p\) 个位置开始的后缀,并要求这个字符至少为 \(c\)
考虑转移,因为这里有个「至少」,第一个转移是直接从 \(dp[p][c+1][l][r]\) 继承过来
考虑第二个转移
发现在 \([l, r]\) 中一定存在一个 \(c\) 到 \(c+1\) 的分界点,我们枚举这个分界点
同时如果我们强令为 \(c\) 的那些数与输入冲突了就break掉
于是这部分的转移方程为
\]
这样就(在一定程度上)转化成了对两个字符串的处理
记得要把长度不够的串用‘a'-1补成一样长
Code:
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 100010
#define ll long long
#define ull unsigned long long
#define reg register int
//#define int long long
int n;
char s[55][25];
int len[55], maxl;
const ll mod=990804011ll, base=131;
inline void md(ll& a, ll b) {a+=b; a=a>=mod?a-mod:a;}
namespace force{
ull p[25];
inline ull hashing(ull* h, int l, int r) {return h[r]-h[l-1]*p[r-l+1];}
ll dfs(int u, char* t, ull ht, ull hs, bool lim) {
//cout<<"dfs "<<u<<' '<<ht<<' '<<hs<<' '<<lim<<endl;
if (u>n) return 1;
ull h[25]; h[0]=0; bool full=1;
//cout<<"len: "<<len[u]<<endl;
for (reg i=1; i<=len[u]; ++i) {
//cout<<"i: "<<i<<endl;
if (s[u][i]=='?') {
full=0; ll ans=0;
//cout<<"pos1"<<endl;
for (reg j=(lim?t[i]-'a'+1:0); j<26; ++j) {
s[u][i]='a'+j; h[i]=h[i-1]*base+s[u][i];
ans+=dfs(u, t, ht, h[i], lim&&(s[u][i]==t[i]));
}
s[u][i]='?';
return ans;
}
else {
h[i]=h[i-1]*base+s[u][i];
if (lim && s[u][i]<t[i]) return 0;
if (lim && s[u][i]!=t[i]) lim=0;
}
}
if (full && !lim) return dfs(u+1, s[u], h[len[u]], 0, 1);
return 0;
}
void solve() {
printf("%lld\n", dfs(1, s[0], 0, 0, 0));
exit(0);
}
}
namespace task1{
ull p[25];
struct st{int u; ull ht, hs; bool lim; st(int a, ull b, ull c, bool d):u(a),ht(b),hs(c),lim(d){}};
struct st_hash{inline size_t operator () (st a) const {return hash<ull>()(a.ht*a.hs);}};
inline bool operator == (st a, st b) {return a.u==b.u&&a.ht==b.ht&&a.hs==b.hs&&a.lim==b.lim;}
unordered_map<st, ll, st_hash> mp{5000, st_hash()};
inline ull hashing(ull* h, int l, int r) {return h[r]-h[l-1]*p[r-l+1];}
ll dfs(int u, char* t, ull ht, ull hs, bool lim) {
//cout<<"dfs "<<u<<' '<<ht<<' '<<hs<<' '<<lim<<endl;
if (u>n) return 1;
st sit(u, ht, hs, lim);
if (mp.find(sit)!=mp.end()) return mp[sit];
ull h[25]; h[0]=0; bool full=1;
//cout<<"len: "<<len[u]<<endl;
for (reg i=1; i<=len[u]; ++i) {
//cout<<"i: "<<i<<endl;
if (s[u][i]=='?') {
full=0; ll ans=0;
//cout<<"pos1"<<endl;
for (reg j=(lim?t[i]-'a'+1:0); j<26; ++j) {
s[u][i]='a'+j; h[i]=h[i-1]*base+s[u][i];
ans+=dfs(u, t, ht, h[i], lim&&(s[u][i]==t[i])), ans%=mod;
}
s[u][i]='?';
mp[sit]=ans;
return ans;
}
else {
h[i]=h[i-1]*base+s[u][i];
if (lim && s[u][i]<t[i]) {mp[sit]=0; return 0;}
if (lim && s[u][i]!=t[i]) lim=0;
}
}
if (full && !lim) {
mp[sit]=dfs(u+1, s[u], h[len[u]], 0, 1);
return mp[sit];
}
return 0;
}
void solve() {
printf("%lld\n", dfs(1, s[0], 0, 0, 0)%mod);
exit(0);
}
}
namespace task{
ll dp[25][30][52][52];
ll dfs(int p, int c, int l, int r) {
//cout<<"dfs "<<p<<' '<<c<<' '<<l<<' '<<r<<endl;
if (~dp[p][c][l][r]) return dp[p][c][l][r];
if (l>r) return dp[p][c][l][r]=1;
if (p>maxl) return dp[p][c][l][r]=(l==r);
if (c>26) return dp[p][c][l][r]=0;
dp[p][c][l][r]=dfs(p, c+1, l, r);
for (int i=l; i<=r; ++i) {
//if (s[i][p]!=27&&s[i][p]!=c) break;
if (!(s[i][p]==c || (s[i][p]==27&&c))) break;
md(dp[p][c][l][r], dfs(p+1, 0, l, i)*dfs(p, c+1, i+1, r)%mod);
}
return dp[p][c][l][r];
}
void solve() {
memset(dp, -1, sizeof(dp));
printf("%lld\n", dfs(1, 0, 1, n));
exit(0);
}
}
signed main()
{
scanf("%d", &n);
for (reg i=1; i<=n; ++i) {
scanf("%s", s[i]+1);
len[i]=strlen(s[i]+1);
maxl=max(maxl, len[i]);
for (int j=1; j<=len[i]; ++j)
if (s[i][j]=='?') s[i][j]=27;
else s[i][j]-='`';
}
//if (n*maxl<=10) force::solve();
//else task1::solve();
task::solve();
return 0;
}
题解 Medium Counting的更多相关文章
- 【题解】Counting D-sets(容斥+欧拉定理)
[题解]Counting D-sets(容斥+欧拉定理) 没时间写先咕咕咕. vjCodeChef - CNTDSETS 就是容斥,只是难了一二三四五\(\dots \inf\)点 题目大意: 给定你 ...
- 20210819 Emotional Flutter,Medium Counting,Huge Counting,字符消除2
考场 T1 一下想到了这题,将白块缩短 \(s\) 后维护类似的区间即可. T2 T3 俩计数,直接跳了. T4 的可行 \(t\) 集合相同相当与从 \(n\) 往前跳 kmp 数组,途径点相同,从 ...
- LeetCode题解之Counting Bits
1.题目描述 2.问题分析 利用bitset. 3 代码 vector<int> countBits(int num) { vector<int> v; ; i <= n ...
- PAT甲题题解-1004. Counting Leaves (30)-统计每层叶子节点个数+dfs
统计每层的叶子节点个数建树,然后dfs即可 #include <iostream> #include <cstdio> #include <algorithm> # ...
- PAT甲题题解-1049. Counting Ones-数学问题
n位数,总共有0~10^n-1共计10^n个数那么所有数出现的总次数变为n*(10^n)个数1出现的次数便是十分之一,所以n位数中,1出现的次数为n*10^(n-1)知道这一个后,接下来就方便求了. ...
- PAT甲题题解-1115. Counting Nodes in a BST (30)-(构建二分搜索树+dfs)
题意:给出一个序列,构建二叉搜索树(BST),输出二叉搜索树最后两层的节点个数n1和n2,以及他们的和sum: n1 + n2 = sum 递归建树,然后再dfs求出最大层数,接着再dfs计算出最后两 ...
- [考试反思]1114csp-s模拟测试115:零迟
最后一次了,允许自己混进榜里吧. 没有心态,原题不会做(真的忘了) T2的搜索没有分. 「 零 · 迟 」:酷刑 只有在最后的时刻才开始意识到,一切的一切都已经晚了. 就在眼前了.没有机会了. 退役, ...
- noip模拟44[我想我以后会碰见计数题就溜走的]
noip模拟44 solutions 这一场抱零的也忒多了,我也只有45pts 据说好像是把几套题里面最难的收拾出来让我们考得 好惨烈啊,这次的考试我只有第一题骗了40pts,其他都抱零了 T1 Em ...
- 2021.8.19考试总结[NOIP模拟44]
T1 emotional flutter 把脚长合到黑条中. 每个黑条可以映射到统一区间,实际操作就是左右端点取模.长度大于$k$时显然不合法. 然后检查一遍区间内有没有不被黑条覆盖的点即可. 区间端 ...
随机推荐
- webpack(10)webpack-dev-server搭建本地服务器
前言 当我们使用webpack打包时,发现每次更新了一点代码,都需要重新打包,这样很麻烦,我们希望本地能搭建一个服务器,然后写入新的代码能够自动检测出来,这时候就需要用到webpack-dev-ser ...
- U149791 正多边形变换
原博客网页--洛谷博客 题目地址 如果您对群论有所了解,那么本题就是对二面体群 \(D_{2n}\) 的简单实现,您可以直接跳到代码部分.下面的解题思路只是对二面体群 \(D_{2n}\) 的构造思路 ...
- 20道Java实习生笔试面试选择题(内附答案解析)
1.以下对继承的描述错误的是(A) A.Java中的继承允许一个子类继承多个父类 B.父类更具有通用性,子类更具体 C.Java中的继承存在的传递性 D.当实例化子类时会递归调用父类中的构造方法 解 ...
- VisibleDeprecationWarning , Creating an ndarray from ragged nested sequences... 警告怎么办
我不是完美主义,但是至少,我在做实验的时候不能容忍有 warning 的出现. 今天使用 tensorflow.keras.datasets中的 imdb 数据集,使用 imdb.load_data( ...
- C语言代码段
/* 功 能:将str字符串中的oldstr字符串替换为newstr字符串 * 参 数:str:操作目标 oldstr:被替换者 newstr:替换者 * 返回值:返回替换之后的字符串 */ char ...
- C语言字符串处理库函数大全(转)
一.string.h中字符串处理函数 在头文件<string.h>中定义了两组字符串函数.第一组函数的名字以str开头:第二组函数的名字以mem开头. 只有函数memmove对重叠对象间的 ...
- gitlab部署及汉化
目录 Git 简介 部署 1. 配置yum源(推荐) 2. 安装 配置GitLab 1.加载配置 2.修改git默认访问端口 gitlab.rb unicorn.rb gitlab-http.conf ...
- C语言:字符型数据(常量)
字符型数据就是字符. 字符型数据的表示 字符型数据是用单引号括起来的一个字符.例如:'a'.'b'.'='.'+'.'?'都是合法字符型数据.在C语言中,字符型数据有以下特点: 字符型数据只能用单引号 ...
- uni-app中当uni.navigateTo传的参数为object时,通过传递的不同参数,在显示单页面内通过v-if判断显示出对应的内容(可实现多页面效果)
通过uni-app中当uni.navigateTo传的参数为object时,通过传递的不同参数,在显示单页面内通过v-if判断显示出对应的内容(可实现多页面效果) 起始页跳转到对应页面,并传递参数(o ...
- 手写一个超简单的Vue
基本结构 这里我根据自己的理解模仿了Vue的单文件写法,通过给Vue.createApp传入参数再挂载元素来实现页面与数据的互动. 其中理解不免有错,希望大佬轻喷. 收集数据 这里将Vue.creat ...