CSAcademy Prefix Suffix Counting 题解
CSAcademy Prefix Suffix Counting 题解
题意
给你两个数字\(N\)和\(M\),现在\(K\)表示\(M\)的位数。问你从\(1\)到\(N\),有多少个数字满足\(M\)同时是它的前\(K\)个数字和后\(K\)个数字。
思路
我们现在假设\(N\)和\(M\)都是字符串,如果没有特别提及,都作为字符串处理。
假设有一个数字\(S\)大于等于\(1\)小于等于\(N\),我们可以分类讨论它的情况:(同样\(S\)作为字符串处理)
- \(S\)的长度大于等于\(2K\),那么前缀和后缀不会互相影响,中间的空出的没填部分在满足这个数字的值小于等于\(N\)的情况下随便填。
- \(S\)的长度小于\(2K\),那么前缀和后缀会互相重叠,你需要保证它们不会互相冲突,也就是仍旧满足前后缀都是\(M\)。而且,你也没有可以自由地填进去的数字了。
做法
对于上文提到的情况,可以分别实现:
- 我们枚举当前这个串/数字的长度,假如它的总长度小于\(N\)的总长度,那么它一定小于\(N\),中间的空当可以随便填。假如它的总长度等于\(N\)的长度,那么我们枚举某一位,在这一位前,所有的数字都和\(N\)中的一样,这一位的数字比\(N\)的这一位小了,那么后面的就随便填。特别地,有可能这一位在前\(K\)个数字中出现过了,那么中间的所有数位都随便填,或者,中间所有数位都填\(0\)时,当前的数字仍旧比\(N\)大,那么就没有合法方案。
- 同样的,枚举当前串/数字的长度,满足前后缀重叠部分相同这一条件需要快速判断,可以使用
Z或者KMP等字符串匹配方法快速计算。
程序
同做法,使用Z匹配前后缀。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=1000000007;
char s[1000005];//s表示题目中的数字N
char t[1000005];//t表示题目中的数字M
int n,m;//n, m分别表示题目中的N, M的长度
ll pw[1000005],ans;//pw[i]表示10的i次方对mod取模后的大小,ans表示最终答案
bool check(int emp){//check表示中间空出了emp个填0的数位的时候,前后缀是M的数字是否小于等于N,emp<0时,表示前后缀的M重叠了几个位置
char *r=new char[n+1];
memset(r,'0',n+1);
memcpy(r+1+n-(m+emp+m),t+1,m);
memcpy(r+1+n-m,t+1,m);//构造一个前后缀为M的数字,长度小于N时高位补零
bool fl=false,va=true;
for(int i=1;i<=n;i++){
if(r[i]<s[i])fl=true;
if(r[i]>s[i]&&!fl)va=false;
}//判断大小关系(数学意义)
delete[] r;
return va;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
pw[0]=1;
for(int i=1;i<=1000000;i++)pw[i]=pw[i-1]*10%mod;//预处理
cin>>s+1;
n=strlen(s+1);
cin>>t+1;
m=strlen(t+1);
if(check(-m))ans++;//单个M作为数字,这里其实可能会出锅,但数据中没有
int *z=new int[m+1],l=1,r=1;
z[1]=m;
for(int i=2;i<=m;i++){
z[i]=0;
if(i>r){
l=i;r=i-1;
while(r<m&&t[r+1]==t[z[i]+1])r++,z[i]++;
}else{
if(i+z[i-l+1]<=r){
z[i]=z[i-l+1];
}else{
l=i;
z[i]=r-i+1;
while(r<m&&t[r+1]==t[z[i]+1])r++,z[i]++;
}
}
if(i+z[i]-1==m){
if(m+m-z[i]<n||(m+m-z[i]==n&&check(-z[i])))ans++;
}
}
delete[] z;//Z算法
if(m+m<n||(m+m==n&&check(0)))ans++;//计算有数字形如M+M时是否合法
for(int i=1;m+i+m<n;i++){//枚举空出了i个数字时
ans=(ans+pw[i])%mod;
}
if(m+m<n&&check(n-m-m)){
int emp=n-m-m;
bool pref=false,suff=true,suf=false;//pref表示前K个数字是否已经比N小了,这样可以随便填,suff表示M是否小于等于N的K个数字,是就可以让中间的数字全部等于N对应数位
for(int i=1;i<=m;i++){
if(s[i]>t[i])pref=true;
if(s[i+n-m]>t[i])suf=true;
if(s[i+n-m]<t[i]&&!suf)suff=false;
}
if(pref)ans=(ans+pw[emp])%mod;//加上中间任意填的方案
else{
ans=(ans+suff)%mod;//加上suff的方案
for(int i=m+1;i<=n-m;i++){
ans=(ans+pw[n-m-i]*(s[i]-'0'))%mod;//加上当前位前面的数字和N相同,当前位小于N对应数位,后面随便填的方案
}
}
}
cout<<ans%mod<<endl;
return 0;
}
CSAcademy Prefix Suffix Counting 题解的更多相关文章
- mybatis之<trim prefix="" suffix="" suffixOverrides="" prefixOverrides=""></trim>的含义
转自:http://blog.csdn.net/qq_33054511/article/details/70490046 <trim prefix="" suffix=& ...
- mybatis之<trim prefix="" suffix="" suffixOverrides="" prefixOverrides=""></trim>
1.<trim prefix="" suffix="" suffixOverrides="" prefixOverrides=&quo ...
- [USACO17JAN]Promotion Counting 题解
前言 巨佬说:要有线段树,结果蒟蒻打了一棵树状数组... 想想啊,奶牛都开公司当老板了,我还在这里码代码,太失败了. 话说奶牛开个公司老板不应该是FarmerJohn吗? 题解 刚看到这道题的时候竟然 ...
- POJ 2386 Lake Counting 题解《挑战程序设计竞赛》
地址 http://poj.org/problem?id=2386 <挑战程序设计竞赛>习题 题目描述Description Due to recent rains, water has ...
- CF1106A Lunar New Year and Cross Counting 题解
Content 试求出在一个 \(n\times n\) 的地图 \(M\) 中,满足 \(1\leqslant i,j\leqslant n\) 且 \(M_{i,j}=M_{i+1,j+1}=M_ ...
- [LeetCode] Prefix and Suffix Search 前后缀搜索
Given many words, words[i] has weight i. Design a class WordFilter that supports one function, WordF ...
- [Swift]LeetCode745. 前缀和后缀搜索 | Prefix and Suffix Search
Given many words, words[i] has weight i. Design a class WordFilter that supports one function, WordF ...
- 【leetcode】745. Prefix and Suffix Search
题目如下: Given many words, words[i] has weight i. Design a class WordFilter that supports one function, ...
- AtCoder Grand Contest 040 简要题解
从这里开始 比赛目录 A < B < E < D < C = F,心情简单.jpg. Problem A >< 把峰谷都设成 0. Code #include &l ...
随机推荐
- [loj539]旅游路线
考虑枚举加油的位置,当确定某次在第$i$个位置加油后,且下一次到$j$加油,那么$i$到$j$必然会选择不超过$c_{i}$条边且最长的路径,记作$d_{i,j}$ 如果能求出$d_{i,j}$,再设 ...
- 『学了就忘』Linux用户管理 — 50、用户管理相关文件详细说明
目录 1.用户信息文件 2./etc/shadow影子文件 3./etc/group 组信息文件 4.组密码文件 5.用户的家目录 6.用户邮箱目录 7.用户模板目录 总结: 提示:严格的用户权限划分 ...
- springboot访问静态资源404
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring- ...
- 『学了就忘』Linux权限管理 — 56、不可改变位权限(chattr)
目录 1.命令格式 2.查看文件系统属性chattr权限 3.示例 文件系统属性chattr权限,也叫不可改变位权限,该权限没有风险,但是他能限制root用户. 1.命令格式 [root@localh ...
- Codeforces 348C - Subset Sums(根号分治)
题面传送门 对于这类不好直接维护的数据结构,第一眼应该想到-- 根号分治! 我们考虑记[大集合]为大小 \(\geq\sqrt{n}\) 的集合,[小集合]为大小 \(<\sqrt{n}\) 的 ...
- 【GS文献】基因组选择技术在农业动物育种中的应用
中国农业大学等多家单位2017年合作发表在<遗传>杂志上的综述,笔记之. 作者中还有李宁院士,不胜唏嘘. 1.概述 GS的两大难题:基因组分型的成本,基因组育种值(genomic esti ...
- 日常Java 2021/11/15
Applet类 每一个Applet都是java.applet Applet类的子类,基础的Applet类提供了供衍生类调用的方法,以此来得到浏览器上下文的信息和服务.这些方法做了如下事情: 得到App ...
- A Child's History of England.1
A Child's History of England, by Charles Dickens (狄更斯) CHAPTER I ANCIENT ENGLAND AND THE ROMANS If y ...
- day05文件编辑命令
day05文件编辑命令 mv命令:移动文件 mv命令:mv命令用来对文件或目录重新命名,或者将文件从一个目录移到另一个目录中. 格式:mv [原来的文件路径] [现在的文件路径] mv命令后面既可以跟 ...
- Learning Spark中文版--第六章--Spark高级编程(1)
Introduction(介绍) 本章介绍了之前章节没有涵盖的高级Spark编程特性.我们介绍两种类型的共享变量:用来聚合信息的累加器和能有效分配较大值的广播变量.基于对RDD现有的transform ...