【luogu P5320】勘破神机(数学)(数列特征方程)(第一类斯特林数)

勘破神机

题目链接:luogu P5320

题目大意

给你 l,r,k(其中 l,r 很大,k501),求:
1rl+1i=lrCfik
1rl+1i=lrCgik
fn 为一个 2n 的网格往里面放 12 的块填满的方案,gn 则是一个 3n 的网格。

思路

首先 2 的答案我们可以看出答案其实是贴合与斐波那契数列 Fi
具体看一看会发现是 fi=Fi+1,所以记得 l,r 加一。
然后斐波那契嘛,fi=fi1+fi2,然后可以表示成那个带根号的通式嘛。

然后我们通过特征方程这个东西,我们知道如果有一个二阶递推式,我们可以把它表示成一个通项公式。
于是开始了下面的步骤:

2

fi=fi1+fi2
f[n]=55[(1+52)n(152)n]
A=55,α=1+52,B=55,β=152

3

思考要如何推出 f 的值,首先把 f0,f1 求出,因为可以作为边界,而且也是特征方程需要的。

f0=1,f1=3
fi 长度为 2i 的答案(所以记得两个边界要改,但是注意 rl+1 要用之前的值)

于是进行思考,发现可以新放进来一个 23 的,然后有 3 中方法。
然后发现只有这样不够,因为可能会出现这样的:

而且呢,中间的粉色可能不止两个:

然后粉色可以是在 1,2 行或者 2,3 行,所以我们可以列出这样的式子:

fi=3fi1+2(fi2+fi3+...)
fi=3fi1+2(j=0i2fj)
fi1=3fi2+2(j=0i3fj)
fifi1=3fi1fi2
fi=4fi1fi2

搞出了二阶递推式,就直接开始求通项公式吧!

fi4fi1+fi2=0
x24x+1=0
x1=4+232,x2=4232
x1=2+3,x2=23
带入 f0=1,f1=3
Ax1n+Bx2n=fn

A+B=1
A(2+3)+B(23)=3

A(2+3)+(1A)(23)=3
A(2+3)+23A(23)=3
23A=1+3
A=1+323=3+36
A=3+36,B=336
f[n]=3+36(4+232)n+336(4232)n
A=3+36,α=4+232,B=336,β=4232
A=3+36,α=2+3,B=336,β=23


于是我们似乎把 fi 表示成了一个很好的形式,考虑开搞。

fi=Aαi+Bβi
i=0n(fik)
i=0nfi!k!(fik)!
i=0nfik_k!
1k!i=0nj=1k(1)kjs(k,j)fij(斯特林数与下降幂的转化)
(补充:xk¯=j=1ks(k,j)xj
1k!i=1k(1)kis(k,i)j=0nfji

gn,j=i=0nfij
fi=Aαi+Bβi
gn,j=i=0n(Aαi+Bβi)j
gn,j=k=0j(jk)i=0n(Aαi)k(Bβi)jk
gn,j=k=0j(jk)AkBjki=0nαikβi(jk)
gn,j=k=0j(jk)AkBjk1α(n+1)kβ(n+1)(jk)1αkβjk(等比数列求和)

1k!i=1k(1)kis(k,i)j=0nfji
1k!i=1k(1)kis(k,i)gn,i
1k!i=1k(1)kis(k,i)(p=0i(ip)ApBip1(αpβip)n+11αpβip)


小提示:
记得特判等比数列公比为 1

代码

#include<cstdio> #define ll long long #define mo 998244353 using namespace std; const int K = 550; int gen; int T, op, k; ll C[K][K], S[K][K], l, r; ll ksm(ll x, ll y) { ll re = 1; while (y) { if (y & 1) re = re * x % mo; x = x * x % mo; y >>= 1; } return re; } struct complex { ll x, y; complex(ll a = 0, ll b = 0) { x = a; y = b; } }A, B, alpha, beta;//x+sqrt{y} complex operator +(complex x, complex y) { return (complex){(x.x + y.x) % mo, (x.y + y.y) % mo}; } complex operator -(complex x) {return (complex){(mo - x.x) % mo, (mo - x.y) % mo};} complex operator -(complex x, complex y) {return x + (-y);} complex operator *(complex x, complex y) { return (complex){(x.x * y.x + gen * x.y * y.y) % mo, (x.x * y.y + x.y * y.x) % mo}; } complex inv(complex x) { ll fm = ksm((((x.x * x.x - gen * x.y * x.y) % mo + mo) % mo) % mo, mo - 2); return (complex){x.x * fm % mo, (mo - x.y) * fm % mo}; } complex ksm(complex x, ll y) { complex re = complex(1, 0); while (y) { if (y & 1) re = re * x; x = x * x; y >>= 1; } return re; } void Init() { C[0][0] = 1; for (int i = 1; i < K; i++) { C[i][0] = 1; for (int j = 1; j < K; j++) C[i][j] = (C[i - 1][j - 1] + C[i - 1][j]) % mo; } S[0][0] = 1; for (int i = 1; i < K; i++) { for (int j = 1; j < K; j++) S[i][j] = (S[i - 1][j - 1] + (i - 1) * S[i - 1][j] % mo) % mo; } gen = (op == 2) ? 5 : 3; if (op == 2) { A = (complex){0, ksm(5, mo - 2)}; alpha = (complex){ksm(2, mo - 2), ksm(2, mo - 2)}; B = (complex){0, (mo - ksm(5, mo - 2)) % mo}; beta = (complex){ksm(2, mo - 2), (mo - ksm(2, mo - 2)) % mo}; } if (op == 3) { A = (complex){ksm(2, mo - 2), ksm(6, mo - 2)}; alpha = (complex){2, 1}; B = (complex){ksm(2, mo - 2), (mo - ksm(6, mo - 2)) % mo}; beta = (complex){2, mo - 1}; } } ll slove(ll n) { ll ans = 0, jc = 1; ll di = ((k & 1) ? 1 : mo - 1); for (int i = 1; i <= k; i++, di = mo - di) { complex sum; jc = jc * i % mo; for (int p = 0; p <= i; p++) { complex alphabeta = ksm(alpha, p) * ksm(beta, i - p); //你是一个一个一个特判啊啊啊!!! if (alphabeta.x == 1 && alphabeta.y == 0) {//特判公比为1的情况 sum = sum + ((complex){C[i][p], 0} * ksm(A, p) * ksm(B, i - p) * (complex){(n + 1) % mo, 0}); continue; } sum = sum + ((complex){C[i][p], 0} * ksm(A, p) * ksm(B, i - p) * ((complex){1, 0} - ksm(alphabeta, n + 1)) * inv((complex){1, 0} - alphabeta)); } if (sum.y) {printf("f\n"); return -1;} (ans += di * S[k][i] % mo * sum.x % mo) %= mo; } return ans * ksm(jc, mo - 2) % mo; } int main() { scanf("%d %d", &T, &op); Init(); while (T--) { scanf("%lld %lld %d", &l, &r, &k); ll sz = (r - l + 1) % mo; if (op == 2) l++, r++; else l = (l + 1) / 2, r = r / 2; printf("%lld\n", (slove(r) - slove(l - 1) + mo) % mo * ksm(sz, mo - 2) % mo); } return 0; }

__EOF__

本文作者あおいSakura
本文链接https://www.cnblogs.com/Sakura-TJH/p/luogu_P5320.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   あおいSakura  阅读(38)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示