题目链接

CF645E

题意

有一个长为\(n\)的由小写字母组成的字符串,需要用小写字母再填\(m\)位,使最后的字符串中本质不同的子串数量尽量多,答案对\(10^9+7\)取模。

本题数据:\(n,m\le 10^6\),事实上\(n\le10^6,m\le10^{18}\)也可以做

solution

先考虑\(m=0\)的情况,此时字符串确定,令\(f[i]\)表示前\(i\)位字符串中本质不同的子串数量,考虑到第\(i\)位时,新产生的子串是前\(i-1\)位所有本质不同的字符串最后接上第\(i\)位以及第\(i\)位自身。

于是\(f[i]=f[i-1]+f[i-1]+1\),但如果\(a[i](i出的字母)\),曾经在\(last[a[i]]\)处出现过,那么前\(last[a[i]]-1\)位字符串的子串与\(a[i]\)组合而成的字符串会重复,所以\(f[i]=f[i-1]+f[i-1]-f[last[a[i]-1]\)

当\(m>0\)时,为使答案最大,我们需要让靠前的\(last[a[i]]\)尽量小,所以填写时按\(last[i]\)从小到大依次填写一定最优,于是\(O(n+m)\)扫一遍,就可以通过CF645E此题。

发现填写序列时每\(k\)位一个循环,而\(k\le26\),所以可以矩阵快速幂优化到\(O(n+k^3log(m))\),能通过\(m\le10^{18}\)的数据

code

//O(n+m)算法
#include<bits/stdc++.h>
using namespace std;
const int M=1e9+7;
const int N=2e6+10;
int n,m,k,a[N],vis[N],q[N],cnt,f[N],last[N],tot=0;
char s[N];
inline int add(int x,int y,int mod=M){return (x+y>=mod)?x+y-mod:x+y;}
inline int dec(int x,int y,int mod=M){return (x-y<0)?x-y+mod:x-y;}
int main(){
scanf("%d%d",&m,&k);cnt=k;
scanf("%s",s+1);n=strlen(s+1);
for(int i=1;i<=n;++i) a[i]=s[i]-'a'+1;
for(int i=n;i>=1;--i)
if(!vis[a[i]]) q[--cnt]=a[i],vis[a[i]]=1;
for(int i=1;i<=k;++i) if(!vis[i]) q[--cnt]=i;
memset(last,-1,sizeof(last));
for(int i=1;i<=n+m;++i){
if(i>n) a[i]=q[tot],tot=add(tot,1,k);
if(last[a[i]]!=-1) f[i]=dec(add(f[i-1],f[i-1]),f[last[a[i]]-1]);
else f[i]=add(add(f[i-1],f[i-1]),1);
last[a[i]]=i;
}
printf("%d\n",f[n+m]+1);
return 0;
}
//O(n+k^3log(m))算法
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int M=1e9+7;
const int N=4e6+10;
const int K=210;
int n,k,a[N],vis[N],q[N],cnt,f[N],last[N],tot=0,pw[N];
ll m;
char s[N];
inline int add(int x,int y,int mod=M){return (x+y>=mod)?x+y-mod:x+y;}
inline int dec(int x,int y,int mod=M){return (x-y<0)?x-y+mod:x-y;}
struct matrix{
int c[K][K];
void build(int d=0){
for(int i=1;i<=k+1;++i)
for(int j=1;j<=k+1;++j) c[i][j]=0;
for(int i=1;i<=k+1;++i) c[i][i]=d;
}
matrix operator *(matrix x){
matrix ret;ret.build();
for(int i=1;i<=k+1;++i)
for(int j=1;j<=k+1;++j)
for(int w=1;w<=k+1;++w)
ret.c[i][j]=add(ret.c[i][j],1ll*c[i][w]*x.c[w][j]%M);
return ret;
}
};
matrix operator ^(matrix a,ll k){
matrix ret;ret.build(1);
while(k){
if(k&1) ret=ret*a;
a=a*a;k>>=1;
}
return ret;
}
int main(){
scanf("%lld%d",&m,&k);cnt=k;
scanf("%s",s+1);n=strlen(s+1);
for(int i=1;i<=n;++i) a[i]=s[i]-'a'+1;
for(int i=n;i>=1;--i)
if(!vis[a[i]]) q[--cnt]=a[i],vis[a[i]]=1;
for(int i=1;i<=k;++i) if(!vis[i]) q[--cnt]=i;
memset(last,-1,sizeof(last));
int t=min(m,k*1ll);
for(int i=1;i<=n+t;++i){
if(i>n) a[i]=q[tot],tot=add(tot,1,k);
if(last[a[i]]!=-1) f[i]=dec(add(f[i-1],f[i-1]),f[last[a[i]]-1]);
else f[i]=add(add(f[i-1],f[i-1]),1);
last[a[i]]=i;
}
if(m==t) printf("%d\n",f[n+m]+1);
else{
matrix A;A.build();
pw[0]=1;for(int i=1;i<=k+1;++i) pw[i]=2ll*pw[i-1]%M;
A.c[1][k+1]=1;
for(int i=2;i<=k+1;++i){
for(int j=1;j<i-1;++j)
A.c[i][j]=dec(M,pw[i-j-1]);
A.c[i][i-1]=M-1;
A.c[i][k+1]=add(A.c[i][k+1],pw[i-1]);
}
ll c=(m-1)/k,ans=0;m-=c*k;
A=A^c;
for(int i=0;i<=k;++i) ans=add(ans,1ll*f[n+i]*A.c[m+1][i+1]%M);
printf("%d\n",ans+1);
}
return 0;
}

「CF645E」 Intellectual Inquiry的更多相关文章

  1. 「译」JUnit 5 系列:条件测试

    原文地址:http://blog.codefx.org/libraries/junit-5-conditions/ 原文日期:08, May, 2016 译文首发:Linesh 的博客:「译」JUni ...

  2. 「译」JUnit 5 系列:扩展模型(Extension Model)

    原文地址:http://blog.codefx.org/design/architecture/junit-5-extension-model/ 原文日期:11, Apr, 2016 译文首发:Lin ...

  3. JavaScript OOP 之「创建对象」

    工厂模式 工厂模式是软件工程领域一种广为人知的设计模式,这种模式抽象了创建具体对象的过程.工厂模式虽然解决了创建多个相似对象的问题,但却没有解决对象识别的问题. function createPers ...

  4. 「C++」理解智能指针

    维基百科上面对于「智能指针」是这样描述的: 智能指针(英语:Smart pointer)是一种抽象的数据类型.在程序设计中,它通常是经由类型模板(class template)来实做,借由模板(tem ...

  5. 「JavaScript」四种跨域方式详解

    超详细并且带 Demo 的 JavaScript 跨域指南来了! 本文基于你了解 JavaScript 的同源策略,并且了解使用跨域跨域的理由. 1. JSONP 首先要介绍的跨域方法必然是 JSON ...

  6. 「2014-5-31」Z-Stack - Modification of Zigbee Device Object for better network access management

    写一份赏心悦目的工程文档,是很困难的事情.若想写得完善,不仅得用对工具(use the right tools),注重文笔,还得投入大把时间,真心是一件难度颇高的事情.但,若是真写好了,也是善莫大焉: ...

  7. 「2014-3-18」multi-pattern string match using aho-corasick

    我是擅(倾)长(向)把一篇文章写成杂文的.毕竟,写博客记录生活点滴,比不得发 paper,要求字斟句酌八股结构到位:风格偏杂文一点,也是没人拒稿的.这么说来,arxiv 就好比是 paper 世界的博 ...

  8. 「2014-3-17」C pointer again …

    记录一个比较基础的东东-- C 语言的指针,一直让人又爱又恨,爱它的人觉得它既灵活又强大,恨它的人觉得它太过于灵活太过于强大以至于容易将人绕晕.最早接触 C 语言,还是在刚进入大学的时候,算起来有好些 ...

  9. 「2014-3-13」Javascript Engine, Java VM, Python interpreter, PyPy – a glance

    提要: url anchor (ajax) => javascript engine (1~4 articles) => java VM vs. python interpreter =& ...

随机推荐

  1. Maven1详解

    Maven详解(一)------ Maven概述   目录 1.引言 2.常规项目开发存在的问题 3.什么是 Maven ? 4.Maven 的历史 5.Maven 的目标 6.Maven 的理念 回 ...

  2. Flutter - 自定义Dialog弹窗

    ------------恢复内容开始------------ Flutter - 自定义Dialog弹窗 应用场景:app系统版本升级弹窗,系统退出登录弹窗,首页广告弹窗,消息中心弹窗,删除文件弹窗等 ...

  3. origin把点图和线图放在一起

    首先分别做好点图和线图在两个graph中,然后选中其中一副图(点图或者线图),然后按下图选择: 如果有多个图,可以在弹出窗口中选择多个sheet.

  4. Python opencv resize图片并保存原有的图像比例

    参考链接:https://www.jianshu.com/p/3092835eab61 现有的图像是高瘦高瘦的,所以直接resize成矩形不合适.改变了整个结构. 所以采用的是先resize再padd ...

  5. D. Regular Bridge 解析(思維、圖論)

    Codeforce 550 D. Regular Bridge 解析(思維.圖論) 今天我們來看看CF550D 題目連結 題目 給你一個\(k\le100\),請構造出一個至少有一個Bridge的,每 ...

  6. Java学习的第五十六天

    1.例11.5引用保护成员 public class Cjava { public static void main(String[]args) { Student1 s1=new Student1( ...

  7. How to using code find the menu label of Menus【X++】

    // VAR Changed by Xie Yu Fan.Fandy 谢宇帆 static void XIE_FindMenu(Args _args) { Dialog dlg = new Dialo ...

  8. 5、Django之模板层

    一 模板简介 在刚刚介绍完的视图层中我们提到,浏览器发送的请求信息会转发给视图函数进行处理,而视图函数在经过一系列处理后必须要有返回信息给浏览器.如果我们要返回html标签.css等数据给浏览器进行渲 ...

  9. VS中Dev控件在工具箱里的不见的解决办法

    出现问题:调整了VS中Dev控件后(以免生成程序每次都要在客户机上面注册dev),之前安装的DEV控件在vs工具箱中消失了,重装可以解决,但是太费时间了,检测dev自带的设置,找到了解决办法. 解决办 ...

  10. Statistical physics approaches to the complex Earth system(相关系统建模理念方法的摘要)

    本文翻译自"Statistical physics approaches to the complex Earth system",其虽然是针对复杂地球系统的统计物理方法的综述,但 ...