【RQNOJ85】三个袋子【矩阵乘法】
题目大意:
题目链接:http://www.rqnoj.cn/problem/85
求个球装进个袋子里的总方案数。
思路:
出题人十分良心的给出了表:
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | |
---|---|---|---|---|---|---|---|---|---|---|
方案数 | 1 | 2 | 5 | 14 | 41 | 122 | 365 | 1094 | 3281 | 9842 |
然后就变成了一道找规律的题目。
40分做法:
容易发现。暴力递推即可。
20到100分做法:
可以发现公式。直接用快速幂,多少分要看你打的好不好。。。
100分做法:
矩阵乘法加速递推。
可以发现矩阵:
然后递推即可。
代码:
#include <cstdio>
#include <cstring>
using namespace std;
int n,MOD,f[3];
int a[3][3]=
{
{0,0,0},
{0,3,0},
{0,1,1}
};
void mul(int f[3],int a[3][3])
{
int c[3];
memset(c,0,sizeof(c));
for (int i=1;i<=2;i++)
for (int j=1;j<=2;j++)
c[i]=((c[i]+f[j]*a[j][i])%MOD+MOD)%MOD;
memcpy(f,c,sizeof(c));
}
void mulself(int a[3][3])
{
int c[3][3];
memset(c,0,sizeof(c));
for (int i=1;i<=2;i++)
for (int j=1;j<=2;j++)
for (int k=1;k<=2;k++)
c[i][j]=((c[i][j]+a[i][k]*a[k][j])%MOD+MOD)%MOD;
memcpy(a,c,sizeof(c));
}
int main()
{
scanf("%d%d",&n,&MOD);
f[1]=1;
f[2]=-1;
n--;
while (n)
{
if (n&1) mul(f,a);
n>>=1;
mulself(a);
}
printf("%d",f[1]%MOD);
return 0;
}