zoukankan      html  css  js  c++  java
  • BZOJ_4870_[Shoi2017]组合数问题_矩阵乘法

    BZOJ_4870_[Shoi2017]组合数问题_矩阵乘法

    Description

    Input

    第一行有四个整数 n, p, k, r,所有整数含义见问题描述。
    1 ≤ n ≤ 10^9, 0 ≤ r < k ≤ 50, 2 ≤ p ≤ 2^30 − 1

    Output

    一行一个整数代表答案。

    Sample Input

    2 10007 2 0

    Sample Output

    8

    设$f[i][j]$表示$i$个球,取出$m(m$%$k=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]$。
    可以构造矩阵,$i->i,i->(i+1)$%$k$ 。
    然后乘$nk$次,$v[0][r]$为答案。
     
    代码:
    #include <stdio.h>
    #include <string.h>
    #include <algorithm>
    #include <map>
    using namespace std;
    typedef long long ll;
    ll mod;
    int n,m,r;
    struct Mat {
    	ll v[51][51];
    	Mat(){memset(v,0,sizeof(v));}
    	Mat operator*(const Mat &x)const {
    		Mat re;int i,j,k;
    		for(i=0;i<m;i++) {
    			for(j=0;j<m;j++) {
    				for(k=0;k<m;k++) {
    					(re.v[i][j]+=v[i][k]*x.v[k][j]%mod)%=mod;
    				}
    			}
    		}
    		return re;
    	}
    };
    Mat qp(Mat x,ll y) {
    	Mat I;
    	int i;
    	for(i=0;i<m;i++) I.v[i][i]=1;
    	while(y) {
    		if(y&1ll) I=I*x;
    		x=x*x;
    		y>>=1ll;
    	}
    	return I;
    }
    int main() {
    	scanf("%d%lld%d%d",&n,&mod,&m,&r);
    	int i;
    	Mat x;
    	for(i=0;i<m-1;i++) x.v[i][i+1]++; x.v[m-1][0]++;
    	for(i=0;i<m;i++) x.v[i][i]++;
    	Mat T=qp(x,1ll*m*n);
    	printf("%lld
    ",T.v[0][r]);
    }
    
  • 相关阅读:
    如何判断某个变量是否是数组?
    mac vscode编辑器的快捷键
    vue require.context()动态文件引入
    在vue项目上使用less
    nrm是什么
    对象的扩展方法
    es5严格模式
    微信公众号定位不准问题
    layer使用iframe的路径不对问题
    form表单中reset对js赋值的表单象无法重置问题
  • 原文地址:https://www.cnblogs.com/suika/p/8893246.html
Copyright © 2011-2022 走看看