P5550 Chino的数列 题解

提供一个只需要推一个转移矩阵的做法。

思路

n 很小,k 很大,考虑矩阵加速递推。为了方便叙述,下文默认 n=4,s=1,m=2

{an} 经过一组操作后变为 {bn}。定义转移矩阵 P,使得 [a1an]×P=[b1bn]

如果只有平移操作,转移矩阵很显然:

[0001100001000010]

如果先平移再交换,交换第 s 列与第 m 列即可:

[0001010010000010]

考虑把先交换再平移转换为先平移再交换。

s,ms,m 向前平移后的位置,则 s=(s+n2)modn+1,m=(m+n2)modn+1

容易发现,交换第 s 列与第 m 列即可。

n=4,s=1,m=2 时,s=4,m=1,转移矩阵为:

[1000000101000010]

代码

#include <cstdio>
#include <cstring>
#define F(x) for(int x = 1;x <= n;++x)
int n, s, m;long long k;
struct S
{
    long long a[100][100];S() {memset(a, 0, sizeof a);}S operator*(S b)
    {S c;F(k) F(i) F(j) c.a[i][j] += a[i][k] * b.a[k][j];return c;}
}p, q;
int main()
{
    scanf("%d%d%d%lld", &n, &s, &m, &k);
    s = (s + n - 2) % n + 1;m = (m + n - 2) % n + 1;
    for(int i = 1;i <= n;++i)
    {
        scanf("%lld", &q.a[1][i]);if(i == s) p.a[m % n + 1][i] = 1;
        else if(i == m) p.a[s % n + 1][i] = 1;else p.a[i % n + 1][i] = 1;
    }
    for(;k;k >>= 1, p = p * p) if(k & 1) q = q * p;
    for(int i = 1;i <= n;++i) printf("%lld ", q.a[1][i]);return 0;
}
posted @   Jijidawang  阅读(5)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示