正题
luogu
CF232B
题目大意
给你一个 n×mn\times mn×m 的网格,问你有多少种放点方案可以满足每个 n×nn\times nn×n 的网格内都恰好有 kkk 个点
解题思路
不难发下,n×nn\times nn×n 的格子往下移一行,新的一行和刚过的一行点的数量一样
那么设 fi,jf_{i,j}fi,j 表示前 iii 行放了 jjj 个点的方案数,然后直接暴力转移即可
code
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
#define N 110
#define mod 1000000007
using namespace std;
ll n,m,k,inv[N],fac[N],ifac[N],g[N][N],f[N][N*N];
ll C(ll x,ll y)
{return fac[x]*ifac[x-y]%mod*ifac[y]%mod;
}
ll pw(ll x,ll y)
{ll z=1;while(y){if(y&1)z=z*x%mod;x=x*x%mod;y>>=1;}return z;
}
void pre_work()
{ifac[0]=fac[0]=inv[1]=ifac[1]=fac[1]=1;for(ll i=2;i<=n;++i){inv[i]=mod-mod/i*inv[mod%i]%mod;fac[i]=fac[i-1]*i%mod;ifac[i]=ifac[i-1]*inv[i]%mod;}for(ll i=1;i<=n;++i)for(ll j=0;j<=n;++j)g[i][j]=pw(C(n,j),(m-i+n)/n);//第i行选j个点的方案数,幂为后面一样的行return;
}
int main()
{scanf("%lld%lld%lld",&n,&m,&k);pre_work();f[0][0]=1;for(ll i=1;i<=n;++i)for(ll j=0;j<=k;++j)for(ll l=0;l<=min(j,n);++l)(f[i][j]+=f[i-1][j-l]*g[i][l]%mod)%=mod;printf("%lld",f[n][k]);return 0;
}