[DP 倍增] BZOJ 4870 [Shoi2017]组合数问题

来源:互联网 发布:mac版office2016下载 编辑:程序博客网 时间:2024/05/22 12:44

就是求 nk 个物品里面取 模kr 个物品的方案数
这个直接dp fi,j表示前 i 个 余 j 个的方案数
矩阵快速幂是O(k3logn)
实际上这个转移满足结合律 直接在快速幂的时候转移就好了
另一种理解是 这个矩阵是循环矩阵 矩阵的记录和乘法都只要处理第一行就好了
复杂度是O(k2logn)
代码比想象中短

#include<cstdio>#include<cstdlib>#include<algorithm>using namespace std;typedef long long ll;int n,P,k,r;int a[55],b[55],t[55];inline void mul(int *a,int *b){  for (int i=0;i<k;i++) for (int j=0;j<k;j++) (t[(i+j)%k]+=(ll)a[i]*b[j]%P)%=P;  for (int i=0;i<k;i++) a[i]=t[i],t[i]=0;}int main(){  freopen("t.in","r",stdin);  freopen("t.out","w",stdout);  scanf("%d%d%d%d",&n,&P,&k,&r);  a[0]++; b[0]++; b[1%k]++;  for (ll y=(ll)n*k;y;y>>=1,mul(b,b))    if (y&1)      mul(a,b);  printf("%d\n",a[r]);  return 0;}
0 0
原创粉丝点击