您的位置:首页 > 其它

{题解}[jzoj4787]【NOIP2016提高A组模拟9.17】数格子

2016-09-20 12:23 465 查看
另设传送门

Description



Analysis

骨牌填矩阵的模型,

显然N与N-1间是有关联的!

递推难以保证合法性,

考虑状压DP

设f[i][s]上一列状态为S,本列是i+1列

剩下的自己YY吧。

这样是O(n)的

不要忘了矩阵快速幂优化加速。

Code

#include<cstdio>
#include<cstring>
#include<algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn = 16;
long long n,m;
long long c[maxn][maxn],f[maxn][maxn],A[maxn][maxn],B[maxn][maxn];//临时数组,DP数组,临时数组,友矩阵
bool bz[16]={1,0,0,1,0,0,0,0,0,1,0,0,1,0,0,1};//0 3 6 12 15 即可转移至f[i][15]的s
void mul_a() //矩阵乘法
{
memset(c,0,sizeof(c));
for(int i = 0;i <= 15;i ++)
for(int j = 0;j <= 15;j ++)
for(int k = 0;k <= 15;k ++)
c[i][j] = (c[i][j] + (f[i][k] * A[k][j]) % m) % m;
memcpy(f,c,sizeof(c));
}
void sqr_a() //矩阵乘法
{
memset(c,0,sizeof(c));
for(int i = 0;i <= 15;i ++)
for(int j = 0;j <= 15;j ++)
for(int k = 0;k <= 15;k ++)
c[i][j] = (c[i][j] + (A[i][k] * A[k][j]) % m) % m;
memcpy(A,c,sizeof(c));
}
void qsm_f(long long n) //矩阵快速幂
{
for(;n;n>>=1)
{
if (n & 1 == 1)
mul_a(); //f = f * A
sqr_a();//A = A * A
}
}
int main()
{
for(int i = 0;i <= 15;i ++)
for(int j = 0;j <= 15;j ++)
if((i & j) == 0 && bz[i | j])
B[i][j]=1;
//求友矩阵
scanf("%lld%lld", &n, &m);
while (n + m > 0)
{
memcpy(A,B,sizeof(B));
memset(f,0,sizeof(f));
//初始化
f[0][0] = 1;
qsm_f(n);
printf("%lld\n", f[0][0]);
scanf("%lld%lld", &n, &m);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: