BZOJ 4870

4870: [Shoi2017]组合数问题

Time Limit: 10 Sec  Memory Limit: 512 MB
Submit: 723  Solved: 379
[Submit][Status][Discuss]

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

Source

黑吉辽沪冀晋六省联考

 

HINT

 

 矩阵快速幂可以求组合数

然后这道题的递推什么的其实也是差不多的道理

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#define N 50
#define ll long long
using namespace std;
int read()
{
    int f=1,x=0;char s=getchar();
    while(s<'0' || s>'9'){if(s=='-')f=-1;s=getchar();}
    while(s>='0' && s<='9'){x=x*10+s-'0';s=getchar();}
    return x*f;
}
ll n,mod,k,r;
struct matrix
{
    ll a[N][N];
    inline void clear()
    {
        memset(a,0,sizeof(a));
    }
    inline void print()
    {
        for(int i=0;i<k;i++)
        {
            for(int j=0;j<k;j++)printf("%d ",a[i][j]);
            printf("\n");
        }
        printf("\n");
    }
}e,tr,ans;
inline matrix operator * (matrix a,matrix b)
{
    matrix c; c.clear();
    for(int i=0;i<k;i++)for(int j=0;j<k;j++)for(int s=0;s<k;s++)
        c.a[i][j]=(c.a[i][j]+(a.a[i][s]%mod)*(b.a[s][j]%mod))%mod;
    return c;
}
inline matrix pow(matrix a,ll p)
{
    matrix ret=e;
    while(p)
    {
        if(p&1)ret=ret*a;
        a=a*a;
        p>>=1;
    }
    return ret;
}
/*
void debug()
{
    matrix x=e;
    for(int i=0;i<n;i++)x=x*tr,x.print();
}*/
int main()
{
    scanf("%lld%lld%lld%lld",&n,&mod,&k,&r);
    ans.a[0][0]=1;
    for(int i=0;i<k;i++)
        e.a[i][i]=1,tr.a[i][i]++,tr.a[i][(i+1)%k]++;
    n*=k;
    
    //debug();
    tr=pow(tr,n);
    ans=ans*tr;
    //ans.print();
    printf("%lld\n",(ans.a[0][r]+mod)%mod);
    
    //tr=tr*tr;
    //tr.print();
    return 0;
}

 

posted @ 2018-03-14 13:11  hyf20010101  阅读(97)  评论(0编辑  收藏  举报