bzoj4870&luogu3746 [六省联考2017]组合数问题

http://www.elijahqi.win/archives/622

题目的大意就是要求我们从n*k个数字中选择%k余r的方案数

bzoj4870&luogu3746 [六省联考2017]组合数问题_第1张图片

定义f(i,j)=∑∞t=0Cj+tki
f(i,j)=f(i−1,j)+f(i−1,(j−1) mod k)

这道题我们转移是用状态转移因为每次都是前一个i-1转移过来的

不妨设当前状态

1 2 3 4 5 6

a b c d e f

那么我们开一个矩阵可以知道

1 2 3 4 5 6

1 1 1

2 1 1

3 1 1

4 1 1

5 1 1

6 1 1

我一开始初值给错了,应该给0~k-1中每个ii都给1

因为我们知道这相当于给取i个为1留了一种可能

#include
#include
#define N 55
struct matrix{
    int f[N][N],l,c;
}ans,m;
int n,p,k,r;
inline matrix multiply(matrix a,matrix b){
    matrix c;memset(c.f,0,sizeof(c.f));
    c.l=a.l;c.c=b.c;
    for (int i=0;ifor (int j=0;jfor (int z=0;zlong long) a.f[i][z]*b.f[z][j]%p+c.f[i][j])%p;
            }
    return c;
}
int main(){
    freopen("3746.in","r",stdin);
    scanf("%d%d%d%d",&n,&p,&k,&r);long long t=(long long)n*k;
    m.c=m.l=k;
    for (int i=0;i1+k)%k][i]++;
    ans.c=k;ans.l=k;
    for (int i=0;i1;
    for (;t;t>>=1,m=multiply(m,m)){
        if (t&1) ans=multiply(m,ans);
    }
    printf("%d",ans.f[0][r]);
    return 0;
}

你可能感兴趣的:(动态规划,快速幂,矩阵乘法)