@zzzc18
2017-09-24T08:45:38.000000Z
字数 1613
阅读 1972
TEST

这里采用颜色数来进行计数(不然岂不是不可做?)
然后就顺理成章地有了以下内容

上述算法复杂度是 显然不可接受
但是我们考虑 的过程就类似于矩阵的乘法()
这样,把 作为左边的矩阵, 作为右边的矩阵,答案就是
#include<cstdio>#include<cstring>#include<algorithm>using namespace std;typedef long long LL;const LL MAXN = 109;const LL MOD = 998244353;LL n,m,p,q;LL C[MAXN][MAXN];LL f[MAXN][MAXN];LL g[MAXN];struct Matrix{LL num[MAXN][MAXN];Matrix(){memset(num,0,sizeof(num));}};Matrix operator * (Matrix A,Matrix B){LL i,j,k;Matrix re;for(i=1;i<=p;i++){for(j=1;j<=p;j++){for(k=1;k<=p;k++){re.num[i][j]=(re.num[i][j]+A.num[i][k]*B.num[k][j])%MOD;}}}return re;}LL qpow_num(LL x,LL k){LL i;LL re=1,tmp=x;for(i=1;i<=k;i<<=1){if(i&k){re*=tmp;re%=MOD;}tmp*=tmp;tmp%=MOD;}return re;}void INIT(){LL i,j;C[0][0]=1;for(i=1;i<MAXN;i++){C[i][0]=C[i][i]=1;for(j=1;j<i;j++){C[i][j]=(C[i-1][j]+C[i-1][j-1])%MOD;}}f[0][0]=1;for(i=1;i<MAXN;i++){for(j=1;j<MAXN;j++){f[i][j]=(f[i-1][j-1]*(p-(j-1))%MOD+f[i-1][j]*j%MOD)%MOD;}}for(i=0;i<MAXN;i++)g[i]=f[n][i];}LL calg(LL x){return g[x]*qpow_num(C[p][x],MOD-2)%MOD;}void solve(){Matrix ans,trans;for(int i=1;i<=p;i++)ans.num[1][i]=g[i];LL i,j,k;for(i=1;i<=p;i++){for(j=1;j<=p;j++){for(k=max(q,max(i,j));k<=min(p,i+j);k++){trans.num[i][j]=(trans.num[i][j]+C[i][i+j-k]*C[p-i][k-i])%MOD;}trans.num[i][j]=(calg(j)*trans.num[i][j])%MOD;}}m--;for(i=1;i<=m;i<<=1){if(m&i){ans=ans*trans;}trans=trans*trans;}LL ANS=0;for(i=1;i<=p;i++){ANS=(ANS+ans.num[1][i])%MOD;}printf("%lld\n",ANS);}int main(){freopen("color.in","r",stdin);freopen("color.out","w",stdout);scanf("%lld%lld%lld%lld",&n,&m,&p,&q);INIT();solve();return 0;}
