LINK:牛牛的斐波那契字符串

虽然sb的事实没有改变 但是 也不会改变。

赛时 看了E和F题 都不咋会写 所以弃疗了。

中午又看了一遍F 发现很水 差分了一下就过了。

这是下午和古队长讨论+看题解的神仙做法的时候 突然想到的。

问题的难点在于 a和b的长度有可能是小于s的 所以递推不了 只能暴力。

暴力的背后藏着正解。可以发现当a和b的长度扩大到大于s时 容易发现 每次s匹配的 不可能横跨a b了 所以此时只有可能是a的后缀接b的后缀 或者b的后缀接a的后缀。

而这个我们可以递推式子分奇偶考虑。然后 就可以直接递推了。

题解的神仙做法是 杜教BM 不过 做法过于神仙 也没有学习的必要 所以弃疗。

直接考虑矩阵乘法 这个东西 虽然带系数不过 矩阵是可以列出的 还很容易 我列了一个\(4\cdot 4\)的。

细节比较繁琐。值得注意。

const ll MAXN=1000010;
ll n,ans,cnt=2,ww=2,d1,d2;
ll nex[MAXN],f[4],g[4];
string a[2],s,cc;
inline void KMP(string b)
{
ll j=-1;ans=0;
for(ui ll i=0;i<b.size();++i)
{
while(j!=-1&&s[j+1]!=b[i])j=nex[j];
if(b[i]==s[j+1])++j;
if(j==(ll)s.size()-1){j=nex[j];++ans;}
}
}
struct wy
{
ll a[4][4];
wy(){memset(a,0,sizeof(a));}
inline wy friend operator *(wy a,wy b)
{
wy c;
rep(0,3,i)rep(0,3,j)rep(0,3,k)
c.a[i][j]=(c.a[i][j]+a.a[i][k]*b.a[k][j])%mod;
return c;
}
inline wy friend operator ^(wy a,ll p)
{
while(p)
{
if(p&1)
{
rep(0,3,i)g[i]=f[i],f[i]=0;
rep(0,3,i)rep(0,3,j)f[i]=(f[i]+a.a[j][i]*g[j])%mod;
}
p=p>>1;a=a*a;
}
return a;
}
}T;
signed main()
{
//freopen("1.in","r",stdin);
ios::sync_with_stdio(false);
cin>>n;cin>>a[0];cin>>a[1];cin>>s;
memset(nex,-1,sizeof(nex));
ll j=-1;
for(ui ll i=1;i<s.size();++i)
{
while(j!=-1&&s[j+1]!=s[i])j=nex[j];
if(s[j+1]==s[i])++j;
nex[i]=j;
}
if(n==1){KMP(a[0]);putl(ans);return 0;}
if(n==2){KMP(a[1]);putl(ans);return 0;}
ll w1=0,w2=1;//putl(ww);
while(a[0].size()<s.size()||a[1].size()<s.size())
{
a[w1]=a[w1]+a[w2];
swap(w1,w2);++ww;
if(ww==n){KMP(a[w2]);putl(ans);return 0;}
}
//求出递推常数 d1和d2.偶数为 w2+w1 奇数为w2+w2;
//cout<<a[w1]<<' '<<a[w2]<<endl;putl(ww);
ll kk=a[w2].size()-s.size()+1;
for(ui i=kk;i<a[w2].size();++i)cc+=a[w2][i];
for(ui i=0;i<s.size()-1;++i)cc+=a[w2][i];
//cout<<cc<<endl;
KMP(cc);d1=ans;cc="";//putl(ans);
for(ui i=kk;i<a[w2].size();++i)cc+=a[w2][i];
for(ui i=0;i<s.size()-1;++i)cc+=a[w1][i];
//cout<<cc<<endl;
KMP(cc);d2=ans;cc="";//putl(ans);
a[w1]=a[w1]+a[w2];++ww;
swap(w1,w2);
KMP(a[w1]);f[0]=ans;
KMP(a[w2]);f[1]=ans;
if(ww==n){putl(f[1]);return 0;}
n-=ww;f[2]=d2;f[3]=d1;
T.a[0][1]=T.a[1][0]=T.a[1][1]=T.a[2][1]=T.a[2][3]=T.a[3][2]=1;
T=T^n;putl(f[1]);return 0;
}

最新文章

  1. Partition:分区切换(Switch)
  2. SOA总结(图片打开略慢请知晓)
  3. jQuery获取字符串中两个字符之间的字符
  4. sqlserver如何关闭死锁进程.
  5. C++ Primer : 第十二章 : 动态内存之allocator类
  6. centos6.5 安装iptables
  7. hdu 1059 多重背包 背包指数分块
  8. Python快速入门学习笔记(三)——函数的定义与调用
  9. wpf DataGrid CheckBox列全选
  10. 汇编语言-[BX]和loop指令
  11. QTP自传之录制
  12. HDU_1003Max Sum 简单动归
  13. 易Android登录Demo
  14. js 不要使用new
  15. pc端的企业网站(IT修真院test8)详解1-1
  16. 201521123067 《Java程序设计》第14周学习总结
  17. Debian9桌面设置
  18. SecureCRT自动断开
  19. [PAClient Error] Error: E4356 File does not exist armv7
  20. 安装clickhouse缺少依赖libicudata.so.50()(64bit)

热门文章

  1. 状压DP之炮兵阵地
  2. BUUCTF-Crypyo-No.1
  3. Scala 基础(三):Scala语言快速开发入门
  4. wtforms: remove &#39; fill out this field&#39;
  5. Django框架08 /聚合查询、分组、F/Q查询、原生sql相关
  6. InnoDB表存储结构及keyring加密
  7. 【Nginx】面试官竟然问我Nginx如何生成缩略图,还好我看了这篇文章!!
  8. bzoj3289Mato的文件管理
  9. ffmpeg源码编译环境搭建
  10. Flink之对时间的处理