hdu 2065 "红色病毒"问题 指数型母函数
由题知:
(1+x/1!+x^2/2!+``+x^n/n!)^2*(1+x^2/2!+```)^2
由e^x=1+x/1!+x^2/2!+```知
原式=e^(2*x)*((e^x+e^(-x))/2)^2
=(1/4)*(e^(2*x)+1)^2
=(1/4)*(e^(4*x)+2*e^(2*x)+1)
=(1/4)*(sia(4^n)*(x^n/n!)+2*sia(2^n)*(x^n/n!)+1)
由以上式子可知:
x^n/n!的系数为(4^n+2*2^n+1)/4=4^(n-1)+2^(n-1)+1/4
对于本题只需要计算(4^(n-1)+2^(n-1))%100即可。
其中设计大数取余
2.
一开始以为递推公式是f[n]=2*f[n-1]+2*f[n-2]。但这个公式显然是错的,这个公式相当于限制了A,C必须成对出现,比如ABA这种就计算不到了。
到网上搜了一下才发现原来公式是这样的,设f1[n]为长度为n的序列,A,C都出现偶数次的方法数;f2[n]为长度为n的序列,A出现奇数次,C出现偶数次的方法数;f3[n]为长度为n的序列,A出现偶数次,C出现奇数次的方法数;f4[n]为长度为n的序列,A,C都出现奇数次的方法数。
f1[n] = 2*f1[n-1] + f2[n-1] + f3[n-1];
f2[n] = f1[n-1] + 2*f2[n-1] + f4[n-1];
f3[n] = f1[n-1] + 2*f3[n-1] + f4[n-1];
f4[n] = f2[n-1] + f3[n-1] + 2*f4[n-1];
使用矩阵递推即可。
# include <stdio.h>
# define MATRIX_ORDER 4
# define MOD 100
//一维乘二维矩阵
void mul12n(int a[MATRIX_ORDER], int b[MATRIX_ORDER][MATRIX_ORDER], int c[MATRIX_ORDER])
{
int i, j, rst[MATRIX_ORDER] ;
for (i = 0 ; i < MATRIX_ORDER ; i++)
{
rst[i] = 0 ;
for (j = 0 ; j < MATRIX_ORDER ; j++)
rst[i] = (rst[i] + a[j]*b[j][i]) % MOD ;
}
for (i = 0 ; i < MATRIX_ORDER ; i++)
c[i] = rst[i] ;
}
//二维乘二维矩阵
void muln2n(int a[MATRIX_ORDER][MATRIX_ORDER], int b[MATRIX_ORDER][MATRIX_ORDER], int c[MATRIX_ORDER][MATRIX_ORDER])
{
int i, j ;
int rst[MATRIX_ORDER][MATRIX_ORDER] ;
for (i = 0 ; i < MATRIX_ORDER ; i++)
mul12n (a[i], b, rst[i]) ;
for (i = 0 ; i < MATRIX_ORDER ; i++)
for (j = 0 ; j < MATRIX_ORDER ; j++)
c[i][j] = rst[i][j] ;
}
//矩阵快速幂
void matrix_qpow(int a[MATRIX_ORDER][MATRIX_ORDER], int c[MATRIX_ORDER][MATRIX_ORDER], unsigned long long n)
{
int i, j ;
int rst[MATRIX_ORDER][MATRIX_ORDER], buf[MATRIX_ORDER][MATRIX_ORDER] ;
for (i = 0 ; i < MATRIX_ORDER ; i++)
for (j = 0 ; j < MATRIX_ORDER ;j++)
{
rst[i][j] = 0 ;
if (i == j) rst[i][j] = 1 ;
buf[i][j] = a[i][j] ;
}
while (n)
{
if (n&1) muln2n(rst, buf, rst) ;
muln2n (buf, buf, buf) ;
n >>= 1 ;
}
for (i = 0 ; i < MATRIX_ORDER ; i++)
for (j = 0 ; j < MATRIX_ORDER ; j++)
c[i][j] = rst[i][j] ;
}
int main ()
{
int c[4], a[4] = {1, 0, 0, 0} ;
int b[4][4] = {2, 1, 1, 0, 1, 2, 0, 1, 1, 0, 2, 1, 0, 1, 1, 2} ;
int rear[4][4] ;
int T, Case ;
long long n ;
while (~scanf ("%d", &T) && T)
{
Case = 1 ;
while (T--)
{
scanf ("%I64u", &n) ;
matrix_qpow(b, rear, n) ;
mul12n(a, rear, c) ;
printf ("Case %d: %d\n", Case++, c[0]) ;
}
printf ("\n") ;
}
return 0 ;
}