LOJ 3090 「BJOI2019」勘破神机——斯特林数+递推式求通项+扩域
题目:https://loj.ac/problem/3090
题解:https://www.luogu.org/blog/rqy/solution-p5320
1.用斯特林数把下降幂化为普通的幂次求和
2.找出通项公式,使得幂次变成二项式,进而将 [ l , r ] 的部分变成等比数列求和
3.模 998244353 下没有 \( \sqrt{5} \) ,所以“扩域”,就是把数表示成 \( a+b*\sqrt{5} \) ;\( \sqrt{3} \) 也同理
注意扩域之后,不满足费马小定理,所以快速幂的指数不能对 ( mod-1 ) 取模!!!
还是不太知道怎么求的通项。为什么是 \( f[n]=A*x_{1}^{n}+B*x_{2}^{n} \) 的形式呢?如果不是二阶怎么推?
UPD:
设特征根是 x1,x2,...,xk,因为 x^n 是通解,又有线性性(?),所以通项可以写成 \( f(i)=A*x_1^i + B*x_2^i + ... \)
但是有重根的话就不是这样。 k 重根的系数是次数界为 k 的多项式。这里的次数指的是 i 的几次幂。
(k重根是针对根而言的,比如一个六次方程,x1=x2=2 , x3=5 , x4=x5=x6=1,那么 2 是2重根,5是单根,1是3重根)
比如,\( f_i = 2*f_{i-1} - f_{i-2} \),\( f_0 = 1 , f_1 = 2 \)
解出特征根是 x1=x2=1 ,那么可以设通项公式为 \( f(i)=(A*i+B)x^i \) ,解得 A=B=1 。
又如,\( f_i = 4*f_{i-1} - f_{i-2} \) , \( f_0 = 1 , f_1 = 7 \)
解出特征根是 x1=x2=2 ,设通项是 \( f(i)=(A*i+B)x^i \) ,解得 \( A=\frac{5}{2} , B=1 \)
^ ^
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
ll rdn()
{
ll ret=;bool fx=;char ch=getchar();
while(ch>''||ch<''){if(ch=='-')fx=;ch=getchar();}
while(ch>=''&&ch<='')ret=ret*+ch-'',ch=getchar();
return fx?ret:-ret;
}
const int N=,mod=;
int upt(int x){while(x>=mod)x-=mod;while(x<)x+=mod;return x;}
int pw(int x,ll k)
{int ret=;while(k){if(k&)ret=(ll)ret*x%mod;x=(ll)x*x%mod;k>>=;}return ret;} int k,s1[N][N],c[N][N],bs,tlen2,ans;ll tl,tlen;
struct Node{
int x,y;
Node(int x=,int y=):x(x),y(y) {}
Node operator+ (const Node &b)const
{ return Node(upt(x+b.x),upt(y+b.y));}
Node operator- (const Node &b)const
{ return Node(upt(x-b.x),upt(y-b.y));}
Node operator* (const Node &b)const
{ return Node(((ll)x*b.x+(ll)bs*y%mod*b.y)%mod,((ll)y*b.x+(ll)x*b.y)%mod);}
}A[N],B[N],x1[N],x2[N],one;
Node pw(Node x,ll k)
{ Node ret=Node(,);
while(k){if(k&)ret=ret*x;x=x*x;k>>=;}return ret;}
Node Inv(Node u)
{
int tp=upt(((ll)u.x*u.x-(ll)bs*u.y%mod*u.y)%mod);
tp=pw(tp,mod-);
return Node((ll)u.x*tp%mod,upt(-(ll)u.y*tp%mod));
}
void init(int lx)
{
s1[][]=;
for(int i=;i<=k;i++)
for(int j=;j<=i;j++)
s1[i][j]=(s1[i-][j-]+(ll)s1[i-][j]*(i-))%mod;
for(int i=;i<=k;i++)c[i][]=;
for(int i=;i<=k;i++)
for(int j=;j<=i;j++)
c[i][j]=upt(c[i-][j-]+c[i-][j]); one=Node(,);
if(lx==)
{
int tp=pw(,mod-); A[]=Node(,tp); B[]=Node(,upt(-tp));
tp=pw(,mod-); x1[]=Node(tp,tp); x2[]=Node(tp,upt(-tp));
}
else
{
int tp=pw(,mod-); A[]=Node((ll)*tp%mod,tp);
B[]=Node((ll)*tp%mod,upt(-tp));
x1[]=Node(,); x2[]=Node(,upt(-));
}
A[]=one; for(int i=;i<=k;i++)A[i]=A[i-]*A[];
B[]=one; for(int i=;i<=k;i++)B[i]=B[i-]*B[];
x1[]=one; for(int i=;i<=k;i++)x1[i]=x1[i-]*x1[];
x2[]=one; for(int i=;i<=k;i++)x2[i]=x2[i-]*x2[];
}
Node cal(Node x)
{
if(x.x==&&x.y==)return Node(tlen2,);//tlen2 not tlen!!!
Node d=Inv(one-x);
d=d*pw(x,tl)*(one-pw(x,tlen));
return d;
}
void solve2()
{
ll l=rdn(),r=rdn(); k=rdn(); bs=; init();
int iv=pw((r-l+)%mod,mod-); l++; r++;
tl=l; tlen=(r-l+); tlen2=(r-l+)%mod;
for(int i=,fx=((k&)?upt(-):);i<=k;i++,fx=upt(-fx))
{
int tp=;
for(int j=;j<=i;j++)
{
Node tmp=x1[j]*x2[i-j];
Node d=cal(tmp)*A[j]*B[i-j];
tp=(tp+(ll)c[i][j]*d.x)%mod;
}
ans=(ans+(ll)s1[k][i]*fx%mod*tp)%mod;
}
ans=(ll)ans*iv%mod;
int ml=; for(int i=;i<=k;i++)ml=(ll)ml*i%mod;
ans=(ll)ans*pw(ml,mod-)%mod;
}
void solve3()
{
ll l=rdn(),r=rdn(); k=rdn(); bs=; init();
int iv=pw((r-l+)%mod,mod-); l=(l+)>>; r=r>>;
tl=l; tlen=(r-l+); tlen2=(r-l+)%mod;
for(int i=,fx=((k&)?upt(-):);i<=k;i++,fx=upt(-fx))
{
int tp=;
for(int j=;j<=i;j++)
{
Node tmp=x1[j]*x2[i-j];
Node d=cal(tmp)*A[j]*B[i-j];
tp=(tp+(ll)c[i][j]*d.x)%mod;
}
ans=(ans+(ll)s1[k][i]*fx%mod*tp)%mod;
}
ans=(ll)ans*iv%mod;
int ml=; for(int i=;i<=k;i++)ml=(ll)ml*i%mod;
ans=(ll)ans*pw(ml,mod-)%mod;
}
int main()
{
int op=rdn(); op=rdn();
if(op==)solve2(); else solve3();
printf("%d\n",ans);
return ;
}
LOJ 3090 「BJOI2019」勘破神机——斯特林数+递推式求通项+扩域的更多相关文章
- loj 3090 「BJOI2019」勘破神机 - 数学
题目传送门 传送门 题目大意 设$F_{n}$表示用$1\times 2$的骨牌填$2\times n$的网格的方案数,设$G_{n}$$表示用$1\times 2$的骨牌填$3\times n$的网 ...
- 【LOJ】#3090. 「BJOI2019」勘破神机
LOJ#3090. 「BJOI2019」勘破神机 为了这题我去学习了一下BM算法.. 很容易发现这2的地方是\(F_{1} = 1,F_{2} = 2\)的斐波那契数列 3的地方是\(G_{1} = ...
- LOJ 2304 「NOI2017」泳池——思路+DP+常系数线性齐次递推
题目:https://loj.ac/problem/2304 看了各种题解…… \( dp[i][j] \) 表示有 i 列.第 j 行及以下默认合法,第 j+1 行至少有一个非法格子的概率,满足最大 ...
- Loj #3089. 「BJOI2019」奥术神杖
Loj #3089. 「BJOI2019」奥术神杖 题目描述 Bezorath 大陆抵抗地灾军团入侵的战争进入了僵持的阶段,世世代代生活在 Bezorath 这片大陆的精灵们开始寻找远古时代诸神遗留的 ...
- Loj #3093. 「BJOI2019」光线
Loj #3093. 「BJOI2019」光线 题目描述 当一束光打到一层玻璃上时,有一定比例的光会穿过这层玻璃,一定比例的光会被反射回去,剩下的光被玻璃吸收. 设对于任意 \(x\),有 \(x\t ...
- [BJOI2019]勘破神机(斯特林数,数论)
[BJOI2019]勘破神机(斯特林数,数论) 题面 洛谷 题解 先考虑\(m=2\)的情况. 显然方案数就是\(f_i=f_{i-1}+f_{i-2}\),即斐波那契数,虽然这里求出来是斐波那契的第 ...
- [BJOI2019]勘破神机
[BJOI2019]勘破神机 推式子好题 m=2,斐波那契数列,$f_{n+1}$项 不妨$++l,++r$,直接求$f_n$ 求$\sum C(f_n,k)$,下降幂转化成阶乘幂,这样都是多项式了, ...
- LOJ 3089 「BJOI2019」奥术神杖——AC自动机DP+0/1分数规划
题目:https://loj.ac/problem/3089 没想到把根号之类的求对数变成算数平均值.写了个只能得15分的暴力. #include<cstdio> #include< ...
- LOJ 3094 「BJOI2019」删数——角标偏移的线段树
题目:https://loj.ac/problem/3094 弱化版是 AGC017C . 用线段树维护那个题里的序列即可. 对应关系大概是: 真实值的范围是 [ 1-m , n+m ] :考虑设偏移 ...
随机推荐
- tp框架视图层view——模板继承
在做网站的时候,每个网站都有头部和尾部,也就是菜单栏和页脚,网站的各个子网页的头部和尾部基本就是一样的,所以tp框架提供了一种模板继承的方法: 1.首先在View的Main文件夹下建立一个base.h ...
- 同余dp
先验知识: 余数的计算公式:c = a -⌊ a/b⌋ * b 其中,⌊ ⌋为向下取整运算符,向下取整运算称为Floor,用数学符号⌊ ⌋表示 题目: Consider an arbitrary se ...
- Bootstrap 学习笔记11 按钮和折叠插件
复选框: <div class="btn-group" data-toggle="buttons"> <label for="se ...
- 题解1433. 数码问题 (Standard IO)
Description Alice有一个N*N的格子,把1-N^2按照从上到下从左到右的顺序填进表格中,允许在表格上进行两种操作: (1) 旋转行——这一行的数向右移动一个位置,而最后一列的数会移到第 ...
- C#调取接口时报错:服务器提交了协议冲突. Section=ResponseStatusLine
private Dictionary<string, Object> GetLocation(string imei) { #region===代码=== string serviceAd ...
- jmeter对响应数据做断言
单独校验某个接口中的某个字段时,断言就相当于检查点 添加http请求,输入路径url
- centos 6.x 配置 mail 发送外部邮件详解和 sendmail 使用简介
一.mail基本配置 1.配置:vim /etc/mail.rc 在文件末尾追加以下内容: set from=@.com # 别名<123456789@163.com> set smtp= ...
- Codeforces Round #535 E2-Array and Segments (Hard version)
Codeforces Round #535 E2-Array and Segments (Hard version) 题意: 给你一个数列和一些区间,让你选择一些区间(选择的区间中的数都减一), 求最 ...
- P4036 [JSOI2008]火星人(splay+hash+二分)
P4036 [JSOI2008]火星人 Splay维护hash,查询二分 $a[x].vl=a[lc].vl*ha[a[rc].sz+1]+a[x].w*ha[a[rc].sz]+a[rc].vl$ ...
- SQL 一次插入多次数据
数据插入 INSERT INTO 表名称 VALUES (值1, 值2,....) 指定所要插入数据的列 INSERT INTO table_name (列1, 列2,...) VALUES (值1, ...