(矩阵快速幂)CF102302H. Log Concave Sequences

CF102302H. Log Concave Sequences

题意&思路:

有n位数,每位只包含0,1,2,要求对于每个位置,ai2>=ai-1*ai+1。求这样的数有多少。
对于答案的3,我们可以列举:

000    001   002  010  011  012  020  021  022
100    101×  102× 110  111  112× 120  121  122
200    201×  202× 210  211× 212× 220  221  222
(×为不满足)

那么我们在寻找第四位的时候只需要在三位合法的情况下,寻找第四位能够使前三位合法的解。这样我们就将问题变成了dp。由后两位的值,决定第三位的个数。dp[i][j][k]表示第i位,j,k表示后两位的值。
可得:
dp[i][0][0]=dp[i-1][0][0]+dp[i-1][1][0]+dp[i-1][2][0]
dp[i][0][1]=dp[i-1][0][0]
dp[i][0][2]=dp[i-1][0][0]
dp[i][1][0]=dp[i-1][0][1]+dp[i-1][1][1]+dp[i-1][2][1]
dp[i][1][1]=dp[i-1][0][1]+dp[i-1][1][1]
dp[i]1][2]=dp[i-1][0][1]
dp[i][2][0]=dp[i-1][0][2]+dp[i-1][1][2]+dp[i-1][2][2]
dp[i][2][1]=dp[i-1][0][2]+dp[i-1][1][2]+dp[i-1][2][2]
dp[i][2][2]=dp[i-1][0][2]+dp[i-1][1][2]+dp[i-1][2][2]
由于N高达1018,递推肯定T,就可以用矩阵快速幂。
计算矩阵:
[ 1 0 0 1 0 0 1 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 ] N − 3 \left[ \begin {matrix} 1&0&0&1&0&0&1&0&0\\ 1&0&0&0&0&0&0&0&0\\ 1&0&0&0&0&0&0&0&0\\ 0&1&0&0&1&0&0&1&0\\ 0&1&0&0&1&0&0&0&0\\ 0&1&0&0&0&0&0&0&0\\ 0&0&1&0&0&1&0&0&1\\ 0&0&1&0&0&1&0&0&1\\ 0&0&1&0&0&1&0&0&1\\ \end{matrix} \right ]^{N-3} 111000000000111000000000111100000000000110000000000111100000000000100000000000111N3
最后计算
∑ i = 1 , j = 1 9 m a t [ i ] [ j ] \sum_{i=1,j=1}^9mat[i][j] i=1,j=19mat[i][j]

代码:

#include
#define pii pair
#define ll long long
#define cl(x,y) memset(x,y,sizeof(x))
#define ct cerr<<"Time elapsed:"<<1.0*clock()/CLOCKS_PER_SEC<<"s.\n";
const int N=1e6+10;
const int mod=1e9+7;
const int maxn=0x3f3f3f3f;
const int minn=0xc0c0c0c0;
const int inf=99999999;
using namespace std;
struct mat
{
	ll maze[10][10];
	mat()
	{
		cl(maze,0);
	}
};
mat mul(mat a,mat b)
{
	mat c;
	int i,j,k;
	for(i=1;i<=9;i++)
		for(j=1;j<=9;j++)
			for(k=1;k<=9;k++)
				c.maze[i][j]=(c.maze[i][j]+a.maze[i][k]*b.maze[k][j])%mod;
	return c;			
} 
mat matpow(mat a,ll n)
{
	mat b;
	int i,j;
	for(i=1;i<=9;i++)
		for(j=1;j<=9;j++)
			b.maze[i][j]=i==j?1:0;
	while(n)
	{
		if(n&1)
			b=mul(b,a);
		a=mul(a,a);
		n>>=1;
	}
	return b;
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	ll n,i,j;
	cin>>n;
	mat a;
	a.maze[1][1]=1;a.maze[1][2]=0;a.maze[1][3]=0;a.maze[1][4]=1;a.maze[1][5]=0;a.maze[1][6]=0;a.maze[1][7]=1;a.maze[1][8]=0;a.maze[1][9]=0;
	a.maze[2][1]=1;a.maze[2][2]=0;a.maze[2][3]=0;a.maze[2][4]=0;a.maze[2][5]=0;a.maze[2][6]=0;a.maze[2][7]=0;a.maze[2][8]=0;a.maze[2][9]=0;
	a.maze[3][1]=1;a.maze[3][2]=0;a.maze[3][3]=0;a.maze[3][4]=0;a.maze[3][5]=0;a.maze[3][6]=0;a.maze[3][7]=0;a.maze[3][8]=0;a.maze[3][9]=0;
	a.maze[4][1]=0;a.maze[4][2]=1;a.maze[4][3]=0;a.maze[4][4]=0;a.maze[4][5]=1;a.maze[4][6]=0;a.maze[4][7]=0;a.maze[4][8]=1;a.maze[4][9]=0;
	a.maze[5][1]=0;a.maze[5][2]=1;a.maze[5][3]=0;a.maze[5][4]=0;a.maze[5][5]=1;a.maze[5][6]=0;a.maze[5][7]=0;a.maze[5][8]=0;a.maze[5][9]=0;
	a.maze[6][1]=0;a.maze[6][2]=1;a.maze[6][3]=0;a.maze[6][4]=0;a.maze[6][5]=0;a.maze[6][6]=0;a.maze[6][7]=0;a.maze[6][8]=0;a.maze[6][9]=0;
	a.maze[7][1]=0;a.maze[7][2]=0;a.maze[7][3]=1;a.maze[7][4]=0;a.maze[7][5]=0;a.maze[7][6]=1;a.maze[7][7]=0;a.maze[7][8]=0;a.maze[7][9]=1;
	a.maze[8][1]=0;a.maze[8][2]=0;a.maze[8][3]=1;a.maze[8][4]=0;a.maze[8][5]=0;a.maze[8][6]=1;a.maze[8][7]=0;a.maze[8][8]=0;a.maze[8][9]=1;
	a.maze[9][1]=0;a.maze[9][2]=0;a.maze[9][3]=1;a.maze[9][4]=0;a.maze[9][5]=0;a.maze[9][6]=1;a.maze[9][7]=0;a.maze[9][8]=0;a.maze[9][9]=1;
	a=matpow(a,n-2);
	ll res=0;
	for(i=1;i<=9;i++)
		for(j=1;j<=9;j++)
			res=(res+a.maze[i][j])%mod;
	cout<<res<<endl;
	return 0;
}

你可能感兴趣的:(比赛)