博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
luogu P5320 [BJOI2019]勘破神机
阅读量:4567 次
发布时间:2019-06-08

本文共 2792 字,大约阅读时间需要 9 分钟。

首先我们要知道要求什么.显然每次放方块要放一大段不能从中间分开的部分.设\(m=2\)方案为\(f\),\(m=3\)方案为\(g\),\(m=2\)可以放一个竖的,或者两个横的,所以\(f_i=f_{i-1}+f_{i-2}\);\(m=3\),因为只有\(i\)为偶数有值,所以后面的\(i\)其实是\(2i\),然后可以发现要么放三个横的,要么像下面这样放长度为偶数的块

|--|   ------|--|   |----|----   |----|

可以注意到每种长度都有两种方案(长度为\(2\)因为有三个横的所以是三种),所以\(g_i=3g_{i-1}+\sum_{j=2}^{i}2g_{i-j}\),打表可以发现其实是\(g_i=4g_{i-1}-g_{i-2}(g_1=3)\).因为要从某种长度中选\(k\)个,所以要求\((m=2)\sum_{i=l}^r \binom{f_i}{k}\).显然只要考虑\([1,r]\)\([1,l-1]\)的值

\(k\)较小,我们可以把组合数看成一个\(k+1\)次项的多项式\(\binom{n}{k}=\frac{1}{k!}\prod_{i=0}^{k}(n-i)\),后面记第\(i\)项系数为\(s_i\),那么我们要求的是\[\sum_{i=1}^n \sum_{j=0}^{k} a_j{f_i}^j\]\[ \sum_{j=0}^{k} a_j\sum_{i=1}^n{f_i}^j\]

后面那个东西不大好求,考虑我们已经知道递推式了,可以利用特征方程解出通项公式,可以去学,所以\(f\)的通项公式是自己去网上找,然后稍微改一下,\(g\)的公式是\(g_n=\frac{3-\sqrt{3}}{6}(2+\sqrt{3})^n+\frac{3+\sqrt{3}}{6}(2-\sqrt{3})^n\),后面为了方便,统一记为\(ab^n+cd^n\)

然后继续推式子\[ \sum_{j=0}^{k} a_j\sum_{i=1}^n(ab^i+cd^i)^j\]

二项式定理展开\[ \sum_{j=0}^{k} a_j\sum_{i=1}^n\sum_{l=0}^{j}\binom{j}{l} (ab^i)^l(cd^i)^{j-l}\]\[ \sum_{j=0}^{k} a_j\sum_{l=0}^{j}\binom{j}{l}\sum_{i=1}^n a^lb^ilc^{j-l}d^{i(j-l)}\]\[ \sum_{j=0}^{k} a_j\sum_{l=0}^{j}\binom{j}{l}a^lc^{j-l}\sum_{i=1}^n (b^ld^{j-l})^i\]

后面可以等比数列求和,然后直接做就行了

注意\(3\)\(5\)在模\(998244353\)意义下没有二次剩余,所以把运算的数记为\(a+b\sqrt{c}\),然后写个类型,定义一下运算就好了

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define LL long long#define db doubleusing namespace std;const int N=1000+20,mod=998244353;LL rd(){ LL x=0,w=1;char ch=0; while(ch<'0'||ch>'9'){if(ch=='-') w=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();} return x*w;}int fpow(int a,int b){int an=1;while(b){if(b&1) an=1ll*an*a%mod;a=1ll*a*a%mod,b>>=1;} return an;}int inv(int a){return fpow(a,mod-2);}int kk,s[N],fac[N],iac[N],bs;int C(int n,int m){return m<0||n
>=1; } return an; }}a,b,c,d,yi;node dbsl(node aa,LL n){return aa.a==1&&aa.b==0?node(n%mod,0):(yi-(aa^n))*((yi-aa).invv());}int sov(LL n){ int an=0; for(int j=0;j<=kk;++j) { node sm; for(int l=0;l<=j;++l) sm=sm+(a^l)*(c^(j-l))*(dbsl((b^l)*(d^(j-l)),n+1)-yi)*C(j,l); an=(an+1ll*s[j]*sm.a%mod)%mod; } return 1ll*an*iac[kk]%mod;}int main(){ yi.a=1; fac[0]=1; for(int i=1;i<=N-10;++i) fac[i]=1ll*fac[i-1]*i%mod; iac[N-10]=inv(fac[N-10]); for(int i=N-10;i;--i) iac[i-1]=1ll*iac[i]*i%mod; int T=rd(),op=rd(); if(op==2) { bs=5; a=node(inv(2),inv(10)),b=node(inv(2),inv(2)),c=node(inv(2),mod-inv(10)),d=node(inv(2),mod-inv(2)); } else { bs=3; a=node(inv(2),mod-inv(6)),b=node(2,1),c=node(inv(2),inv(6)),d=node(2,mod-1); } while(T--) { LL l=rd(),r=rd(),ln=(r-l+1)%mod;kk=rd(); if(op==3) l=(l+1)/2+1,r=r/2+1; memset(s,0,sizeof(int)*(kk+3)); s[0]=1; for(int i=0;i

转载于:https://www.cnblogs.com/smyjr/p/10770506.html

你可能感兴趣的文章
hdu 1018 Big Number 数学结论
查看>>
【MUI】百度地图定位功能
查看>>
bzoj3687 简单题
查看>>
STL容器简介
查看>>
HashMap遍历的两种方式,推荐使用entrySet()
查看>>
如何在Android开发中测试应用在真机上实验
查看>>
传奇代码研究 极品机率...
查看>>
(转)park1.0.0生态圈一览
查看>>
需要学习双拼了
查看>>
Apache Spark大数据分析入门(一)
查看>>
java8使用stream的collect进行list转map注意事项
查看>>
部分和问题
查看>>
进程,线程
查看>>
[。。。]不知道是事故还是故事的东西
查看>>
AtCoder Beginner Contest 073
查看>>
链表的回文结构
查看>>
slqmap简单使用
查看>>
如何禁用或重新启用计算机的休眠功能
查看>>
window函数 resetAccumulator
查看>>
AKKA好文
查看>>