题意:有多少个 的矩阵满足:其所有数字都是 位 进制数,且每一行每一列的或都是 。
首先对于二进制的题很大一部分是逐位处理,因为各二进制位之间互不影响,首先我们注意到 是没有意义的, 我们只要求出 的 矩阵有多少种方案使得每行每列的或都是 即可,记这个答案为 的话, 最后答案即为 。
我们设 表示前 行有 列或为 ,那么 转移到下一行时, 能转移到
当 时, 意味着在 行上所有前 行为 位置是 , 否则一定会出现新的列或为 ,而第 行剩下 列可以随便放,但要注意不能全放 ,排除这种情况,方程即为 。
当 时, 意味着 行在前 行为 的位置上有 列是1,此时第 行剩下 列可以随便放(剩下 列全是 也可以), 方程 。预处理组合数和 的 次幂,最后用快速幂即可。
的初值就是在第一行时从 列中选 位为 的方案数即
```#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define ll long long
using namespace std;
const int mod=1e9+7;
int n,m,kk,t;
ll c[55][55],dp[55][55],pow_2[55];
ll ksm(ll q,ll w)
{
ll h=1;
while(w)
{
if(w&1)
h=h*q%mod;
q=q*q%mod;
w>>=1;
}
return h;
}
int main()
{
cin>>t;
pow_2[0]=1;
for(int i=1;i<=50;++i)
pow_2[i]=(pow_2[i-1]%mod*2%mod)%mod;
for(int i=1;i<=50;++i)
{
c[i][i]=1;
c[i][0]=1;
}
for(int i=1;i<=50;++i)
for(int j=i+1;j<=50;++j)
c[j][i]=(c[j-1][i]%mod+c[j-1][i-1]%mod)%mod;
while(t--)
{
cin>>n>>m>>kk;
memset(dp,0,sizeof(dp));
for(int i=0;i<=m;i++)
dp[1][i]=c[m][i];
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j)
{
dp[i+1][j]=(dp[i+1][j]%mod+(dp[i][j]%mod*(pow_2[j]-1)%mod)%mod)%mod;
for(int k=j+1;k<=m;++k)
dp[i+1][k]=(dp[i+1][k]%mod+(dp[i][j]%mod*c[m-j][k-j]%mod*pow_2[j]%mod)%mod)%mod;
}
cout<<ksm(dp[n][m],kk)<<endl;
}
return 0;
}