链接:https://ac.nowcoder.com/acm/contest/213/A
来源:牛客网
题目描述
一场考试怎么能没有大模拟呢qwq,SKY_magician听说过猪国杀、德州扑克、UNO、杀蚂蚁等等,但是他觉得这些模拟写起来太短了,于是他就设计了一个肯定不会超过1500行的大模拟(划掉)。
现在你有一个4*n的棋盘和一坨地斗主骨牌,这些骨牌都是1*2的。请你求出用骨牌完全覆盖这个棋盘的方案数对m取模的值。
输入描述:
第一行一个T表示数据组数 对于每组数据输入n和m,n和m意义见题目描述。
输出描述:
输出答案
示例1
输入
3 1 10000 3 10000 5 10000
输出
1 11 95
备注:
对于10%的数据 1<=n<=6 对于50%的数据 1<=n<=10000 对于70%的数据 1<=n<=5e7 对于100%的数据 1<=n<=1e9,1<=m<=1e5,T<=1500
代码:
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
#include<stack>
#include<set>
#include<vector>
#include<map>
#include<cmath>
const int maxn=1e5+5;
typedef long long ll;
using namespace std;
ll MOD;
struct mat
{
ll a[5][5];
};
mat Mul(mat a,mat b)
{
mat ans;
memset(ans.a,0,sizeof(ans.a));
for(int t=1;t<=4;t++)
{
for(int j=1;j<=4;j++)
{
for(int k=1;k<=4;k++)
{
ans.a[t][j]=(ans.a[t][j]+a.a[t][k]*b.a[k][j])%MOD;
}
}
}
return ans;
}
mat ans;
ll quickpow(ll n)
{
mat res;
memset(res.a,0,sizeof(res.a));
res.a[1][1]=1;
res.a[1][2]=5;
res.a[1][3]=1;
res.a[1][4]=-1;
res.a[2][1]=1;
res.a[3][2]=1;
res.a[4][3]=1;
while(n)
{
if(n&1)
{
ans=Mul(res,ans);
}
res=Mul(res,res);
n>>=1;
}
return ans.a[1][1];
}
int main()
{
ll n;
int T;
cin>>T;
while(T--)
{
scanf("%lld%lld",&n,&MOD);
memset(ans.a,0,sizeof(ans.a));
ans.a[1][1]=36;
ans.a[2][1]=11;
ans.a[3][1]=5;
ans.a[4][1]=1;
if(n==1)
{
printf("1
");
}
else if(n==2)
{
printf("5
");
}
else if(n==3)
{
printf("11
");
}
else if(n==4)
{
printf("36
");
}
else
{
ll s=quickpow(n-4)+MOD;
printf("%lld
",(s)%MOD);
}
}
return 0;
}