两侧同时换到之前的修订记录 前一修订版 后一修订版 | 前一修订版 | ||
2020-2021:teams:legal_string:jxm2001:contest:牛客练习赛87 [2021/08/21 20:21] jxm2001 |
2020-2021:teams:legal_string:jxm2001:contest:牛客练习赛87 [2021/08/21 22:40] (当前版本) jxm2001 |
||
---|---|---|---|
行 125: | 行 125: | ||
int ans=(frac[n]-(cal(n,m+1)-cal(n,m+2)))%mod; | int ans=(frac[n]-(cal(n,m+1)-cal(n,m+2)))%mod; | ||
enter((ans+mod)%mod); | enter((ans+mod)%mod); | ||
+ | } | ||
+ | return 0; | ||
+ | } | ||
+ | </code> | ||
+ | </hidden> | ||
+ | |||
+ | ===== F - 简洁的题面 ===== | ||
+ | |||
+ | ==== 题意 ==== | ||
+ | |||
+ | $$ | ||
+ | \sum_{i_1=0}^n\sum_{i_2=0}^n\cdots \sum_{i_k=0}^n\sum_{d=1}^g[d\ast(i_1+i_2+\cdots i_k)\le n]\prod_{j=1}^k{n-d\ast \sum_{h=1}^{j-1}i_h\choose d\ast i_j} | ||
+ | $$ | ||
+ | |||
+ | $1\le g,k\le 3,n\le 10^9$ | ||
+ | |||
+ | ==== 题解 ==== | ||
+ | |||
+ | 化简,得上式等于 | ||
+ | |||
+ | $$ | ||
+ | \sum_{d=1}^g\sum_{i_1+i_2+\cdots +i_k\le n}[d\mid i_1,d\mid i_2\cdots d\mid i_k]\frac {n!}{(i_1)!(i_2)!\cdots (i_k)!(n-i_1-i_2-\cdots i_k)!} | ||
+ | $$ | ||
+ | |||
+ | 由于 $g$ 很小,可以暴力枚举 $d$,对固定的 $d$,相当于查询长度为 $n$ 的 $k+1$ 重集排列的个数,满足前 $k$ 种元素出现次数都是 $d$ 的倍数。 | ||
+ | |||
+ | 设 $\text{dp}(n,i_1,i_2\cdots i_k)$ 表示长度为 $n$ 的 $k+1$ 重集排列的个数,满足前 $k$ 种元素出现次数模 $d$ 分别为 $i_1,i_2\cdots i_k$。 | ||
+ | |||
+ | 用 $k$ 位 $d$ 进制数表示状态 $(i_1,i_2\cdots i_k)$,矩阵快速幂加速 $\text{dp}$,时间复杂度 $O\left(g^{3k}\log n\right)$。 | ||
+ | |||
+ | <hidden 查看代码> | ||
+ | <code cpp> | ||
+ | const int MAXS=27; | ||
+ | int mod; | ||
+ | struct Matrix{ | ||
+ | int a[MAXS][MAXS]; | ||
+ | Matrix(int type=0){ | ||
+ | mem(a,0); | ||
+ | if(type){ | ||
+ | _for(i,0,MAXS) | ||
+ | a[i][i]=1; | ||
+ | } | ||
+ | } | ||
+ | Matrix operator * (const Matrix &b)const{ | ||
+ | Matrix c; | ||
+ | _for(i,0,MAXS)_for(j,0,MAXS)_for(k,0,MAXS) | ||
+ | c.a[i][j]=(c.a[i][j]+1LL*a[i][k]*b.a[k][j])%mod; | ||
+ | return c; | ||
+ | } | ||
+ | }; | ||
+ | Matrix quick_pow(Matrix n,int k){ | ||
+ | Matrix ans=Matrix(1); | ||
+ | while(k){ | ||
+ | if(k&1)ans=ans*n; | ||
+ | n=n*n; | ||
+ | k>>=1; | ||
+ | } | ||
+ | return ans; | ||
+ | } | ||
+ | int c[5]; | ||
+ | void decode(int s,int d,int k){ | ||
+ | _for(i,0,k){ | ||
+ | c[i]=s%d; | ||
+ | s/=d; | ||
+ | } | ||
+ | } | ||
+ | int encode(int d,int k){ | ||
+ | int s=0; | ||
+ | for(int i=k-1;i>=0;i--) | ||
+ | s=s*d+c[i]; | ||
+ | return s; | ||
+ | } | ||
+ | int main() | ||
+ | { | ||
+ | int T=read_int(); | ||
+ | while(T--){ | ||
+ | int n,k,g,ans=0; | ||
+ | n=read_int(),k=read_int(),mod=read_int(),g=read_int(); | ||
+ | _rep(d,1,g){ | ||
+ | Matrix m; | ||
+ | int s=1; | ||
+ | _for(i,0,k)s*=d; | ||
+ | _for(i,0,s){ | ||
+ | decode(i,d,k); | ||
+ | m.a[i][i]=1; | ||
+ | _for(j,0,k){ | ||
+ | c[j]=(c[j]+1)%d; | ||
+ | m.a[i][encode(d,k)]++; | ||
+ | c[j]=(c[j]+d-1)%d; | ||
+ | } | ||
+ | } | ||
+ | m=quick_pow(m,n); | ||
+ | ans=(ans+m.a[0][0])%mod; | ||
+ | } | ||
+ | enter(ans); | ||
} | } | ||
return 0; | return 0; |