题目大意:
题目链接:http://www.rqnoj.cn/problem/85
求
n
n
n个球装进
3
3
3个袋子里的总方案数。
思路:
出题人十分良心的给出了表:
n n n | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
---|---|---|---|---|---|---|---|---|---|---|
方案数 | 1 | 2 | 5 | 14 | 41 | 122 | 365 | 1094 | 3281 | 9842 |
然后就变成了一道找规律的题目。
40分做法:
容易发现 f [ i ] = 3 × f [ i − 1 ] − 1 f[i]=3\times f[i-1]-1 f[i]=3×f[i−1]−1。暴力递推即可。
20到100分做法:
可以发现公式 f [ i ] = 3 i − 1 − 1 2 f[i]=\frac{3^{i-1}-1}{2} f[i]=23i−1−1。直接用快速幂,多少分要看你打的好不好。。。
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;
}