4870: [Shoi2017]组合数问题

来源:互联网 发布:seo全网优化指南 编辑:程序博客网 时间:2024/06/16 06:41

4870: [Shoi2017]组合数问题

Time Limit: 10 Sec Memory Limit: 512 MB
Submit: 295 Solved: 158
[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
HINT

Source

黑吉辽沪冀晋六省联考

定义f(i,j)=t=0Cj+tki
打个表不难发现,f(i,j)=f(i1,j)+f(i1,(j1) mod k)
于是大力矩乘就可以了

#include<iostream>#include<cstring>#include<cstdio>using namespace std;const int N = 51;typedef long long LL;int n,K,p,r;inline int Mul(const LL &x,const LL &y) {return x * y % p;}inline int Add(const int &x,const int &y) {return x + y < p ? x + y : x + y - p;}struct data{    int a[N][N]; data(){memset(a,0,sizeof(a));}    data operator * (const data &b)    {        data c;        for (int k = 0; k < K; k++)            for (int i = 0; i < K; i++)                for (int j = 0; j < K; j++)                    c.a[i][j] = Add(c.a[i][j],Mul(a[i][k],b.a[k][j]));        return c;    }}G;data ksm(LL y){    data ret; for (int i = 0; i < K; i++) ret.a[i][i] = 1;    for (; y; y >>= 1LL)    {        if (y & 1LL) ret = ret * G;        G = G * G;    }    return ret;}int main(){    #ifdef DMC        freopen("DMC.txt","r",stdin);    #endif    cin >> n >> p >> K >> r;    for (int i = 0; i < K; i++)        ++G.a[(i - 1 + K) % K][i],++G.a[i][i];    data T = ksm(1LL * n * K);    cout << T.a[0][r] << endl;    return 0;}
0 0
原创粉丝点击