花园
状压dp + 矩阵
题解:
注意到M很小,因此可以状压dp。
然后用矩阵优化一下即可。
因为是环形的,所以要做N次幂,然后取首尾相接的。
Code:
#include <iostream>
#include <cstdio>
#include <cstring>
#define D(x) cout<<#x<<" = "<<x<<" "
#define E cout<<endl
using namespace std;
typedef long long LL;
const LL mod = 1000000007;
LL N,M,K;
struct Matrix{
int x,y;
LL d[55][55];
void clear(){ x=y=0; memset(d,0,sizeof(d)); }
void clone(Matrix &a){
x=a.x; y=a.y;
for(int i=0;i<x;i++)
for(int j=0;j<y;j++)
d[i][j]=a.d[i][j];
}
void print(){
D(x); D(y); E;
for(int i=0;i<x;i++){
for(int j=0;j<y;j++)
printf("%lld ",d[i][j]);
puts("");
}
}
} f;
void mul(Matrix &a,Matrix &b,Matrix &c){
static Matrix res; res.clear();
res.x=a.x; res.y=b.y;
for(int i=0;i<a.x;i++)
for(int j=0;j<a.y;j++){
if(!a.d[i][j]) continue;
for(int k=0;k<b.y;k++)
res.d[i][k] = (res.d[i][k] + a.d[i][j]*b.d[j][k]%mod) %mod;
}
c.clone(res);
}
void pow(Matrix &f,LL t){
static Matrix res; res.clear();
res.x=res.y=f.x;
for(int i=0;i<res.x;i++){ res.d[i][i]=1; }
while(t){
if(t&1) mul(res,f,res);
mul(f,f,f); t>>=1;
}
f.clone(res);
// f.print();
}
int bitcnt(int S){
int cnt=0, A=1;
while(A<=S){
if(A&S) cnt++;
A<<=1;
}
return cnt;
}
void build(){
int ALL=(1<<M)-1;
f.clear();
f.x=f.y=ALL+1;
for(int S=0;S<=ALL;S++){
if(bitcnt(S)>K) continue;
int A=(S<<1)&(ALL);
f.d[S][A]=1;
if(bitcnt(A)<K){ f.d[S][A+1]=1; }
}
// f.print();
}
void solve(){
build();
pow(f,N);
LL ans=0; int ALL=(1<<M)-1;
for(int i=0;i<=ALL;i++){
ans=(ans+f.d[i][i])%mod;
}
cout<<ans<<endl;
}
int main(){
cin>>N>>M>>K;
solve();
}