题解 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$时显然不合法. 然后检查一遍区间内有没有不被黑条覆盖的点即可. 区间端 ...
随机推荐
- ADC电阻分压采集相关知识
1.电池串联可以增加电压,电池并联可以增加电流,都是为了增加电功率.但是电池不宜并联,即使是相同规格的电池,如果消耗不同,电势就会不同,会造成电池之间的放电现象. 2.电阻的作用: 限流:为使通过用电 ...
- STM32笔记二
1.STM32编程通常有两种方法:一种是寄存器编程,另外一种是固件库编程.寄存器编程是基础,而固件库是寄存器编程的基础上升级而来的编程方法,是需要重点掌握的编程方法. 2.STM32F103采用的是C ...
- Jmeter之事务控制器
性能测试的结果统计时我们一定会关注TPS,TPS代表的是每秒事务数,每个事务对应的是我们的请求.虽然JMeter能够帮我们把每个请求统计成一个事务,但有时候我们希望把多个操作统计成一个事务,JMete ...
- Qt Model/view 小实例 文件目录浏览器
1. 文件目录浏览器 直接在main.cpp文件中添加下列代码 #include "mainwindow.h" #include <QApplication> #inc ...
- Java基础00-方法引用32
1. 方法引用 Java8新特征之方法引用 1.1 体验方法引用 代码示例: 需求: 1:定义一个接口(Printable):里面定义一个抽象方法: void printString(String s ...
- ACM金牌选手讲解LeetCode算法《栈和队列的高级应用》
大家好,我是编程熊,双非逆袭选手,字节跳动.旷视科技前员工,ACM金牌,保研985,<ACM金牌选手讲解LeetCode算法系列>作者. 上一篇文章讲解了<线性表>中的数组.链 ...
- React 之 组件生命周期
React 之 组件生命周期 理解1) 组件对象从创建到死亡它会经历特定的生命周期阶段2) React组件对象包含一系列的勾子函数(生命周期回调函数), 在生命周期特定时刻回调3) 我们在定义组件时, ...
- 解决远程连接服务器数据库报错:Host ‘XXXXXX’ is blocked because of many connection errors
参考:https://blog.csdn.net/li_li_lin/article/details/72764683和 https://blog.csdn.net/zaishijizhidian/a ...
- js里的发布订阅模式及vue里的事件订阅实现
发布订阅模式(观察者模式) 发布订阅模式的定义:它定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知. 发布订阅模式在JS中最常见的就是DOM的事件绑定与触发 ...
- element UI表格行高、padding等设置报错问题
element UI里面表格的行高需要自己调整高度和设置padding,直接写style是不行的,里面有 : 1.row-style (行的 style) 2.header-row-styl (表 ...