码迷,mamicode.com
首页 > 其他好文 > 详细

组合数问题题解

时间:2019-10-11 23:14:12      阅读:111      评论:0      收藏:0      [点我收藏+]

标签:namespace   pac   while   operator   水题   为什么   适用于   scanf   inline   

组合数问题题解

水题,但我为什么想不出
屈辱看题解系列~~
就是求n*k中选mod k余r 的方案数之和
我们不妨设一个dp状态:\(f[i][j]\)表示i中选mod k 余 j的方案数之和
显然,\(f[i][j]=\sum_{p=0}^{i/k} C_{i}^{p*k+j}\)
所以,它也适用于\(C_{i}^{j}=C_{i-1}^{j}+C_{i-1}^{j-1}\)的公式啦,
只是注意一下:\(f[i][0]\)可以由\(f[i-1][k-1]\)转移过来就行了。
然后,咕咕咕,就能愉快地写出转移矩阵了。

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=52;
int r;
ll n,k,p;
struct matrix{
   ll z[N][N];
   void clr(){memset(z,0,sizeof(z));}
}g,h;
matrix operator * (matrix u,matrix v){
   matrix ans; ans.clr();
   for(int i=0;i<k;++i) for(int j=0;j<k;++j) for(int q=0;q<k;++q) ans.z[i][j]=(ans.z[i][j]+u.z[i][q]*v.z[q][j]%p)%p;  
   return ans;
}
void ksm(){
   n=n*k;
   while(n){
      if(n&1) g=g*h;
      h=h*h,n>>=1;
   }   
}
int main(){
   scanf("%lld%lld%lld%d",&n,&p,&k,&r);
   g.z[0][0]=1,++h.z[0][0],++h.z[k-1][0];
   for(int i=1;i<k;++i) h.z[i-1][i]=h.z[i][i]=1;
   ksm(),printf("%lld\n",g.z[0][r]);
   return 0;
}

组合数问题题解

标签:namespace   pac   while   operator   水题   为什么   适用于   scanf   inline   

原文地址:https://www.cnblogs.com/ljk123-de-bo-ke/p/11657458.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!