题面
第一印象
题目显得一脸不可做。
扯远一点
一般的来说,读题是不会看前面一些没有什么太大意义的话的。
确实也如此,譬如题面首句
组合数 Cmn 表示的是从n个互不相同的物品中选出m个的方案数
想来大家也是知道的
但是
再观察前面的式子
可以表示成如下形式
∑Qmodk=rCQn∗k
回顾题面首句
(代入?)可以得到讲人话的题面,大致如下:
求从n*k个物品中选取模k为r个物品?
F(n,r)
表示从n个物品选取模k为r个物品的方案数
F(n,r)=F(n−1,r)+F(n−1,(r−1+k)modk)
果断上矩乘!
后面过程不详尽写了
代码
#include <cmath>
#include <algorithm>
#include <cstring>
using namespace std;
typedef long long ll;
char ch;
int fl;
inline void read(int &a){
for(fl=1,ch=getchar();ch<'0'||ch>'9';ch=getchar()) if (ch=='-') fl=-fl;
for(a=0;ch>='0'&&ch<='9';ch=getchar()) (a*=10)+=(ch-'0');
a*=fl;
}
int Mods,k,r,i,j;
ll n;
struct matrix{
ll p[50][50];
inline matrix operator *(const matrix &a){
matrix c;
int i,j,s;
for (i=0;i<k;i++)
for (j=0;j<k;j++)
{
c.p[i][j]=0;
for(s=0;s<k;s++)
(c.p[i][j]+=p[i][s]*a.p[s][j])%=Mods;
}
return c;
}
}d,trans,ans;
inline matrix power(matrix a,ll b){
matrix ans=d,t=a;
for(;b;b>>=1){
if (b&1)ans=ans*t;
t=t*t;
}
return ans;
}
int main()
{
scanf("%lld",&n);
read(Mods);read(k);read(r);
ans.p[0][0]=1;
for(i=0;i<k;i++)
d.p[i][i]=1,trans.p[i][i]++,trans.p[(i-1+k)%k][i]++;
n*=k;
ans=ans*power(trans,n);
printf("%lld\n",ans.p[0][r]);
return 0;
}