upd:20.04.27
考虑把组合数拆成下降幂除掉阶乘
(sum_{i=0}^{n}inom{f_i}{k}=sum_{i=0}^{n}frac{{f_i}^{underline{k}}}{k!}=frac{1}{k!}sum_{i=0}^{n}{f_i}^{underline{k}})
考虑算(sum_{i=0}^{n}{f_i}^{underline{k}}),带入通项公式(f_i=lambda_1alpha^i+lambda_2eta^i)
(sum_{i=0}^{n}{f_i}^{underline{k}}=sum_{i=0}^{n}(lambda_1alpha^i+lambda_2eta^i)^{underline{k}})
(=sum_{i=0}^{n}prod_{j=0}^{k-1}(lambda_1alpha^i+lambda_2eta^i-j))
注意到本题中在(m=2)时(alphaeta=-1),在(m=3)时(alphaeta=1)
所以先考虑(m=3),可得(eta=alpha^{-1}),代入得
(=sum_{i=0}^{n}prod_{j=0}^{k-1}(lambda_1alpha^i+lambda_2alpha^{-i}-j))
设后面柿子展开后((alpha^i)^j)前面系数为(c_j)
(=sum_{i=0}^{n}sum_{j=-k}^{k}c_j(alpha^i)^j)
(=sum_{j=-k}^{k}c_j(sum_{i=0}^{n}alpha^{ij}))
所以用分治fft算出(c_j)后就可以等比数列求和做了
还有(m=2)的情况,这时(alphaeta=-1,eta=-alpha^{-1}),代入后发现当(i)为奇数时(prod)里面(lambda_2)前面符号为负号,否则为正号,这时候分别算奇数偶数的答案即可.总复杂度(O(klog^2k+klog n))
以下是原内容
首先我们要知道要求什么.显然每次放方块要放一大段不能从中间分开的部分.设(m=2)方案为(f),(m=3)方案为(g),(m=2)可以放一个竖的,或者两个横的,所以(f_i=f_{i-1}+f_{i-2});(m=3),因为只有(i)为偶数有值,所以为了方便后面的(i)其实是原来的(2i),然后可以发现要么放三个横的,要么一横两竖,要么像下面这样放长度为偶数的块
|--| ------
|--| |----|
---- |----|
注意到(原来的)长度为(2)有三种方案,其他的都有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 inom{f_i}{k}).显然只要考虑([1,r])和([1,l-1])的值
(k)较小,我们可以把组合数看成一个(k+1)次项的多项式(inom{n}{k}=frac{1}{k!}prod_{i=0}^{k}(n-i)),后面记第(i)项系数为(s_i),那么我们要求的是
(sum_{i=1}^n sum_{j=0}^{k} s_j{f_i}^j)
(sum_{j=0}^{k} s_jsum_{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} s_jsum_{i=1}^n(ab^i+cd^i)^j)
二项式定理展开
(sum_{j=0}^{k} s_jsum_{i=1}^nsum_{l=0}^{j}inom{j}{l} (ab^i)^l(cd^i)^{j-l})
(sum_{j=0}^{k} s_jsum_{l=0}^{j}inom{j}{l}sum_{i=1}^n a^lb^ilc^{j-l}d^{i(j-l)})
(sum_{j=0}^{k} s_jsum_{l=0}^{j}inom{j}{l}a^lc^{j-l}sum_{i=1}^n (b^ld^{j-l})^i)
后面可以等比数列求和,然后直接做就行了
注意(3)和(5)在模(998244353)意义下没有二次剩余,所以把运算的数记为(a+bsqrt{c}),然后写个类型,定义一下运算就好了
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<vector>
#include<cmath>
#include<ctime>
#include<queue>
#include<map>
#include<set>
#define LL long long
#define db double
using 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<m?0:1ll*fac[n]*iac[m]%mod*iac[n-m]%mod;}
struct node
{
int a,b;
node(){a=b=0;}
node(int na,int nb){a=na,b=nb;}
node operator + (const node &bb) const {return node((a+bb.a)%mod,(b+bb.b)%mod);}
node operator - (const node &bb) const {return node((a-bb.a+mod)%mod,(b-bb.b+mod)%mod);}
node operator * (const node &bb) const {return node((1ll*a*bb.a+1ll*b*bb.b%mod*bs)%mod,(1ll*a*bb.b+1ll*b*bb.a)%mod);}
node operator * (const LL &bb) const {return node(1ll*a*bb%mod,1ll*b*bb%mod);}
node invv(){int dt=inv((1ll*a*a-1ll*bs*b*b%mod+mod)%mod);return node(1ll*a*dt%mod,(mod-1ll*b*dt%mod)%mod);}
node operator ^ (const LL &bb) const
{
node an,a=*this;
an.a=1;
LL bbb=bb;
while(bbb)
{
if(bbb&1) an=an*a;
a=a*a,bbb>>=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<kk;++i)
{
for(int j=kk;j;--j) s[j]=(1ll*s[j]*(mod-i)%mod+s[j-1])%mod;
s[0]=1ll*s[0]*(mod-i)%mod;
}
printf("%lld
",1ll*(sov(r)-sov(l-1)+mod)%mod*inv(ln)%mod);
}
return 0;
}