• 【六省联考2017】组合数问题 题解(矩阵快速幂优化DP)


    题目链接

    题目大意:求$(sumlimits_{i=0}^n C_{nk}^{ik+r}) mod p$的值。

    ---------------------

    讲真,一开始看到这个题我都没往DP方面想,以为是什么大力推式子的数学题。

    设$f_{i,j}$表示考虑前$i$个物品,选出的物品$mod k=j$的方案数。最后输出$f_{n,r}$。

    易得转移方程:

    $f_{i,j}=f_{i-1,j}+f_{i-1,j-1}$

    $f_{i,0}=f_{i-1,0}+f_{i-1,k-1}$

    看到数据范围想到矩阵加速,有转移矩阵:

    $egin{bmatrix}1&0&cdots&0&1\1&1&0&cdots&0\0&1&1&cdots&0\vdots&ddots&ddots&ddots&vdots\0&0&cdots&1&1 end{bmatrix}$

    矩阵快速幂乘$nk$次方即可。

    注意当$k=1$时只有一个元素,其初始值为2。

    代码:

    #include<bits/stdc++.h>
    #define int long long
    using namespace std;
    int n,p,k,r;
    struct node
    {
        int a[55][55];
        node(){
            memset(a,0,sizeof(a));
        }
        inline void build(){
            for (int i=1;i<=k;i++) a[i][i]=1;
        }
    };
    node operator * (const node x,const node y)
    {
        node z;
        for (int l=1;l<=k;l++)
            for (int i=1;i<=k;i++)
                for (int j=1;j<=k;j++)
                    z.a[i][j]=(z.a[i][j]+x.a[i][l]*y.a[l][j])%p;
        return z;
    }
    signed main()
    {
        cin>>n>>p>>k>>r;int mi=n*k;
        node a,ans;ans.build();
        for (int i=1;i<=k-1;i++) a.a[i][i]++,a.a[i][i+1]++;
        a.a[k][1]++,a.a[k][k]++;
        while(mi)
        {
            if (mi&1) ans=ans*a;
            a=a*a;
            mi>>=1;
        }
        printf("%lld",ans.a[k][k-r]);
        return 0;
    }
  • 相关阅读:
    Java线程专题 3:java内存模型
    Java线程专题 2:synchronized理解
    Java线程专题 1:线程创建
    设计模式七大原则
    JVM 运行时数据区
    css_selector定位,比xpath速度快,语法简洁
    xpath绝对定位和相对定位
    selenium多种定位
    操作浏览器基本元素(不定时更新)
    爬取网页图片并且下载(1)
  • 原文地址:https://www.cnblogs.com/Invictus-Ocean/p/13346716.html
Copyright © 2020-2023  润新知