zoukankan      html  css  js  c++  java
  • 【BZOJ4870】组合数问题(计数DP,快速幂)

    题意:

    1 ≤ n ≤ 10^9, 0 ≤ r < k ≤ 50, 2 ≤ p ≤ 2^30 − 1

    思路:From http://blog.csdn.net/qq_33229466/article/details/70665582

    实际上就是要我们从nk件物品里面选出若干件,使得其数量模k等于r的方案数。 
    显然的dp方程f[i,j]表示前i件物品拿了若干件使得其数量模k等于j的方案数。 
    那么显然有f[i,j]=f[i1,j]+f[i1,j1] 
    矩阵乘法优化即可。 
    复杂度O(k3logn)

    还有一种更棒的做法,同样是dp,但可以发现f[n2,i+j]+=f[n,i]f[n,j] 
    可以理解成枚举前n个物品的选法和后n个物品的选法。 
    那么直接对dp数组做快速幂即可。 
    复杂度O(k2logn)

     1 type arr=array[0..60]of int64;
     2 var ans,c,a:arr;
     3     n,p,k,r,t:int64;
     4 
     5 procedure dp(var a:arr;b:arr);
     6 var i,j:longint;
     7 begin
     8  for i:=0 to k-1 do c[i]:=0;
     9  for i:=0 to k-1 do
    10   for j:=0 to k-1 do
    11    c[(i+j) mod k]:=(c[(i+j) mod k]+a[i]*b[j] mod p) mod p;
    12  for i:=0 to k-1 do a[i]:=c[i];
    13 end;
    14 
    15 begin
    16  assign(input,'bzoj4870.in'); reset(input);
    17  assign(output,'bzoj4870.out'); rewrite(output);
    18  read(n,p,k,r);
    19  inc(ans[0]); inc(ans[1 mod k]);
    20  a:=ans; t:=n*k-1;
    21  while t>0 do
    22  begin
    23   if t and 1=1 then dp(ans,a);
    24   dp(a,a);
    25   t:=t>>1;
    26  end;
    27  writeln(ans[r]);
    28 
    29  close(input);
    30  close(output);
    31 end.
  • 相关阅读:
    mysql函数
    mysql创建函数槽点
    python类内置方法的再学习
    一个python生成器的使用
    爬虫----配合多线程的思路
    爬虫相关基础技术铺垫---多线程Thread和队列Queue应用
    beautifulsoup4 用法一二
    python和CSV
    :( Call to a member function Table() on a non-object 错误位置
    实习生的苦恼
  • 原文地址:https://www.cnblogs.com/myx12345/p/6761102.html
Copyright © 2011-2022 走看看