bzoj 4870: [Shoi2017]组合数问题

9 篇文章 0 订阅

题意:

求题面上那个乱七八糟的柿子。

题解:

其实是道大傻逼题
千万不要像我一样被那个玩意吓坏了。
地球版题意:在n*k个物品中选若干个物品,使其数量 mod p=r
然后dp+矩乘。
我真是大傻逼
code:

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#define LL long long
using namespace std;
struct node{
    LL n,m,a[55][55];
}em,f;
LL n,mod,k,r;
node operator * (node a,node b)
{
    node ans;ans=em;
    ans.n=a.n;ans.m=b.m;
    for(LL i=0;i<a.n;i++)
        for(LL j=0;j<b.m;j++)
            for(LL k=0;k<a.m;k++)
                (ans.a[i][j]+=a.a[i][k]*b.a[k][j])%=mod;
    return ans;
}
node operator ^ (node a,LL b)
{
    node ans;ans=em;
    ans.n=a.n;ans.m=a.m;
    for(LL i=0;i<a.n;i++) ans.a[i][i]=1;
    while(b)
    {
        if(b&1) ans=ans*a;
        a=a*a;b>>=1;
    }
    return ans;
}
int main()
{
    scanf("%lld %lld %lld %lld",&n,&mod,&k,&r);
    f.n=1;f.m=k;f.a[0][0]=1;
    node a;a.n=a.m=k;
    for(LL i=0;i<k;i++)
        a.a[i][i]++,a.a[(i-1+k)%k][i]++;
    f=f*(a^(n*k));
    printf("%lld",f.a[0][r]);
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值