ARC071_F 题解

RMJ 已经炸了好久了,什么时候能修好啊……

题意简述

定义“好”的序列 {ai} 为满足以下两个性质的无穷序列:

  • 所有项都是 [1,n] 中的正整数。
  • n 项及之后的所有项都相等。
  • 对每一个 ai,满足 ai+1ai+ai 两两之间都相等。

给出 n,求“好”的序列的数量。

题目分析

与其他题解差不多,仍是采用 DP。设 fi 表示第 in 都填好的方案数。那么由于第 n 位及之后的项可以随便填,故 fn=n;同样的道理,第 n1 项也可以随便填,故 fn1=n2

然后考虑状态转移,分三种情况:

  1. ai=1:方案数直接为 fi+1

  2. ai>1,ai+1=1:那么 ai+1ai+ai 都确定为 1,方案数为 ai=2nfi+ai+1。特别地,对 k>n,我们令 fk=1,所以原式实质上等于 i+1+j=i+3nfj

  3. ai,ai+1>1:则 ai+1 及之后的所有项都必须相同。而 aiai+1 可以随便填。方案数为 (n1)2

综上,fi=i+1+(n1)2+fi+1+j=i+3nfj。直接用前缀和维护 j=i+3nfj 进行计算可以做到 O(n)

考虑更优的做法。我们发现计算这个递推式其实可以很方便地用矩阵优化。初步设计答案矩阵为 [fi+1fi+2fi+3i+1(n1)2j=i+4nfj1]

为了将其递推到 [fifi+1fi+2i(n1)2j=i+3nfj1],设计转移矩阵:

[1100000001000010000101001000100010010000100001001]

我们一列一列进行解释:

1 列,由状态转移方程得来。

23 列,简单的滚动更新。

4 列,i+1+(1)=i。第 57 列保持不变。

6 列,fi+3+j=i+4nfj=j=i+3nfj

这样用矩阵快速幂做确实是可行的,但我们会发现 7×7 的矩阵做矩阵乘法一方面会使常数变得很大,另一方面矩阵中的一些项其实是没有必要的。

考虑优化。首先,fi+1+j=i+3nfj 其实就等于 (j=i+1nfj)fi+2,根本没必要维护 fi+3;同时,(n1)2i+1 其实可以合并进前缀和里。这样我们就得到了简化后的 1×4 的答案矩阵:[fi+1fi+2i+1+(n1)2+j=i+2nfj1]

相应地改变转移矩阵:

[1110100010100011]

这样程序的常数就会小不少,总时间复杂度为 O(logn),对本题绰绰有余。

代码实现

#include<bits/stdc++.h>
using namespace std;
const int mod=1000000007;
int n;
struct matrix
{
int n,m;
int a[5][5];
void init(int k)
{
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if(i!=j)
a[i][j]=0;
else
a[i][j]=k;
}
friend matrix operator *(matrix a,matrix b)//矩阵乘法
{
matrix c;
c.n=a.n,c.m=a.m;
c.init(0);
for(int i=1;i<=a.n;i++)
for(int j=1;j<=b.m;j++)
for(int k=1;k<=a.m;k++)
c.a[i][j]=(c.a[i][j]+1ll*a.a[i][k]*b.a[k][j]%mod)%mod;
return c;
}
friend matrix operator ^(matrix a,int b)//矩阵快速幂
{
matrix res;
res.n=res.m=a.n;
res.init(1);
for(;b;b>>=1)
{
if(b&1)
res=res*a;
a=a*a;
}
return res;
}
}fs,tr;
int main()
{
scanf("%d",&n);
if(n==1)
{
printf("1");
return 0;
}//特判 1
fs.n=1,fs.m=tr.n=tr.m=4;
fs.a[1][1]=1ll*n*n%mod,fs.a[1][2]=n,fs.a[1][3]=1ll*n*n%mod,fs.a[1][4]=mod-1;//初始答案矩阵,注意 -1 是 mod-1
tr.init(0);
tr.a[1][1]=tr.a[1][2]=tr.a[1][3]=tr.a[3][1]=tr.a[3][3]=tr.a[4][3]=tr.a[4][4]=1,tr.a[2][1]=mod-1;//转移矩阵
tr=tr^(n-2);//计算转移矩阵的幂
fs=fs*tr;//得到最终答案矩阵
printf("%d",fs.a[1][1]);
return 0;
}
posted @   Hadtsti  阅读(10)  评论(1编辑  收藏  举报  
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
点击右上角即可分享
微信分享提示