【矩阵优化DP】CF 1117D,821E,954F,1182E,1151F

题解以后再写

  • T1:CF1117D Magic Gems
    • title
    • code
  • T2:CF821E Okabe and El Psy Kongroo
    • title
    • code
  • T3:CF954F Runner's Problem
    • title
    • code
  • T4:CF1182E Product Oriented Recurrence
    • title
    • code
  • T5:CF1151F Sonya and Informatics
    • title
    • code

【矩阵优化DP】CF 1117D,821E,954F,1182E,1151F_第1张图片

T1:CF1117D Magic Gems

title

code

#include 
#include 
#define mod 1000000007
#define ll long long
int m;
ll n;

struct Matrix {
	ll c[105][105];
	
	Matrix () {
		memset( c, 0, sizeof( c ) );
	}
	
	Matrix operator * ( const Matrix &p ) const {
		Matrix ans;
		for( int i = 1;i <= m;i ++ )
			for( int j = 1;j <= m;j ++ )
				for( int k = 1;k <= m;k ++ )
					ans.c[i][j] = ( ans.c[i][j] + c[i][k] * p.c[k][j] % mod ) % mod;
		return ans;
	}
	
}A, result;

Matrix qkpow( Matrix a, ll b ) {
	Matrix ans;
	for( int i = 1;i <= m;i ++ ) ans.c[i][i] = 1;
	while( b ) {
		if( b & 1 ) ans = ans * a;
		a = a * a;
		b >>= 1;
	}
	return ans;
}

int main() {
	scanf( "%lld %d", &n, &m );
	for( int i = 2;i <= m;i ++ )
		A.c[i][i - 1] = 1;
	A.c[1][m] = A.c[m][m] = 1;
	result.c[1][m] = 1;
	result = result * qkpow( A, n );	
	printf( "%lld", result.c[1][m] );
}

T2:CF821E Okabe and El Psy Kongroo

title

code

#include 
#include 
#include 
using namespace std;
#define ll long long
#define mod 1000000007
struct Matrix {
	int n, m;
	ll c[16][16];
	
	void clear() {
		n = m = 0;
		memset( c, 0, sizeof( c ) );
	}
	
	Matrix operator * ( const Matrix &p ) const {
		Matrix ans;
		ans.clear();
		ans.n = n, ans.m = p.m;
		for( int i = 0;i <= n;i ++ )
			for( int k = 0;k <= m;k ++ )
				for( int j = 0;j <= p.m;j ++ )
					ans.c[i][j] = ( ans.c[i][j] + c[i][k] * p.c[k][j] % mod ) % mod;	
		return ans;
	}
}v, result;

Matrix qkpow( Matrix a, ll b ) {
	Matrix ans;
	ans.clear();
	ans.n = ans.m = a.n;
	for( int i = 0;i <= ans.n;i ++ )
		ans.c[i][i] = 1;
	while( b ) {
		if( b & 1 ) ans = ans * a;
		a = a * a;
		b >>= 1;
	}
	return ans;
}

int n;
ll k;

int main() {
	result.clear();
	result.n = 15, result.m = 0;
	result.c[0][0] = 1;
	scanf( "%d %lld", &n, &k );
	for( int i = 1;i <= n;i ++ ) {
		ll a, b; int c;
		scanf( "%lld %lld %d", &a, &b, &c );
		b = min( b, k );
		v.clear();
		v.n = v.m = 15;
		for( int j = 0;j <= c;j ++ ) {
			v.c[j][j] = 1;
			if( j ) v.c[j][j - 1] = 1;
			if( j < c ) v.c[j][j + 1] = 1;
		}
		v = qkpow( v, b - a );
		result = result * v;
	}
	printf( "%lld", result.c[0][0] );
	return 0;
}

T3:CF954F Runner’s Problem

title

code

#include 
#include 
#include 
using namespace std;
#define mod 1000000007
#define ll long long
struct Matrix {
	ll c[3][3];
	
	void clear () {
		memset( c, 0, sizeof( c ) );
	}
	
	void zero () {
		c[0][0] = c[1][1] = c[2][2] = c[0][1] = c[1][0] = c[1][2] = c[2][1] = 1;
	}
	
	Matrix operator * ( const Matrix &p ) const {
		Matrix ans;
		ans.clear();
		for( int i = 0;i < 3;i ++ )
			for( int k = 0;k < 3;k ++ )
				for( int j = 0;j < 3;j ++ )
					ans.c[i][j] = ( ans.c[i][j] + c[i][k] * p.c[k][j] % mod ) % mod;
		return ans;
	}
	
};
struct node {
	int a; ll l, r;
}a[10005];
ll b[20010], c[3][20010], f[3];

Matrix qkpow( Matrix x, ll y ) {
	Matrix v;
	v.clear();
	v.c[0][0] = v.c[1][1] = v.c[2][2] = 1;
	while( y ) {
		if( y & 1 ) v = v * x;
		x = x * x, y >>= 1;
	}
	return v;
}

int n, num;
ll m;

int main() {
	scanf( "%d %lld", &n, &m );
	for( int i = 1;i <= n;i ++ ) {
		scanf( "%d %lld %lld", &a[i].a, &a[i].l, &a[i].r );
		a[i].a --;
		b[++ num] = a[i].l - 1;
		b[++ num] = a[i].r;	
	}
	b[++ num] = 1, b[++ num] = m;
	sort( b + 1, b + num + 1 );
	num = unique( b + 1, b + num + 1 ) - b - 1;
	for( int i = 1;i <= n;i ++ ) {
		int l = lower_bound( b + 1, b + num + 1, a[i].l ) - b;
		int r = lower_bound( b + 1, b + num + 1, a[i].r ) - b;
		c[a[i].a][l] ++, c[a[i].a][r + 1] --;
	}
	Matrix ans;
	ans.clear();
	ans.c[1][0] = 1;
	for( int i = 2;i <= num;i ++ ) {
		Matrix v;
		v.clear(), v.zero();
		for( int j = 0;j < 3;j ++ ) {
			f[j] += c[j][i];
			if( f[j] ) v.c[j][0] = v.c[j][1] = v.c[j][2] = 0;
		}
		v = qkpow( v, b[i] - b[i - 1] );
		ans = v * ans;
	}
	printf( "%lld", ans.c[1][0] );
	return 0;
}

T4:CF1182E Product Oriented Recurrence

title

code

#include 
#include 
#define ll long long
#define mod 1000000007
struct Matrix {
	int n, m;
	ll c[6][6];
	
	void clear() {
		n = m = 0;
		memset( c, 0, sizeof( c ) );
	}
	
	Matrix operator * ( const Matrix &p ) const {
		Matrix ans;
		ans.clear();
		ans.n = n, ans.m = p.m;
		for( int i = 1;i <= n;i ++ )
			for( int k = 1;k <= m;k ++ )
				for( int j = 1;j <= p.m;j ++ )
					ans.c[i][j] = ( ans.c[i][j] + c[i][k] * p.c[k][j] % ( mod - 1 ) ) % ( mod - 1 );
		return ans;
	}
}v, p, w;

Matrix qkpow( Matrix x, ll y ) {
	Matrix ans;
	ans.clear();
	ans.n = x.n, ans.m = x.m;
	for( int i = 1;i <= ans.n;i ++ )
		ans.c[i][i] = 1;
	while( y ) {
		if( y & 1 ) ans = ans * x;
		x = x * x, y >>= 1;
	}
	return ans;
}

ll qkpow( ll x, ll y ) {
	ll ans = 1;
	while( y ) {
		if( y & 1 ) ans = ans * x % mod;
		x = x * x % mod, y >>= 1;
	}
	return ans;
}

ll n, f1, f2, f3, c, result = 1;

int main() {
	scanf( "%lld %lld %lld %lld %lld", &n, &f1, &f2, &f3, &c );
	//c
	w.clear(), v.clear();
	w.n = 5, w.m = 1, w.c[5][1] = 2;
	v.n = v.m = 5;
	v.c[1][1] = v.c[1][2] = v.c[1][3] = v.c[1][4] = v.c[1][5]
	= v.c[2][1] = v.c[3][2] = v.c[4][4] = v.c[4][5] = v.c[5][5] = 1;
	v = qkpow( v, n - 3 );
	w = v * w;
	result = result * qkpow( c, w.c[1][1] ) % mod;
	
	v.clear();
	v.n = v.m = 3;
	v.c[1][1] = v.c[1][2] = v.c[1][3] = v.c[2][1] = v.c[3][2] = 1;
	v = qkpow( v, n - 3 );
	//f1
	p.clear();
	p.n = 3, p.m = 1;
	p.c[3][1] = 1;
	p = v * p;
	result = result * qkpow( f1, p.c[1][1] ) % mod;
	//f2
	p.clear();
	p.n = 3, p.m = 1;
	p.c[2][1] = 1;
	p = v * p;
	result = result * qkpow( f2, p.c[1][1] ) % mod;
	//f3
	p.clear();
	p.n = 3, p.m = 1;
	p.c[1][1] = 1;
	p = v * p;
	result = result * qkpow( f3, p.c[1][1] ) % mod;
	printf( "%lld", result );
	return 0;
}

T5:CF1151F Sonya and Informatics

title

code

#include 
#include 
#define mod 1000000007
#define ll long long
struct Matrix {
	ll c[101][101];
	
	void clear () {
		memset( c, 0, sizeof( c ) );
	}
	
	Matrix operator * ( const Matrix &p ) const {
		Matrix ans;
		ans.clear();
		for( int i = 0;i <= 100;i ++ )
			for( int k = 0;k <= 100;k ++ )
				for( int j = 0;j <= 100;j ++ )
					ans.c[i][j] = ( ans.c[i][j] + c[i][k] * p.c[k][j] % mod ) % mod;
		return ans;
	}
	
}v, p;

Matrix qkpow( Matrix x, ll y ) {
	Matrix ans;
	ans.clear();
	for( int i = 0;i <= 100;i ++ )
		ans.c[i][i] = 1;
	while( y ) {
		if( y & 1 ) ans = ans * x;
		x = x * x, y >>= 1;
	}
	return ans;
}

ll qkpow( ll x, ll y ) {
	ll ans = 1;
	while( y ) {
		if( y & 1 ) ans = ans * x % mod;
		x = x * x % mod, y >>= 1;
	}
	return ans;
}

ll n, k, cnt;
int a[105];

int main() {
	scanf( "%lld %lld", &n, &k );
	for( int i = 1;i <= n;i ++ )
		scanf( "%d", &a[i] ), cnt += ( a[i] == 0 );
	int tot = 0;
	for( int i = 1;i <= cnt;i ++ )
		tot += ( a[i] == 0 );
	p.clear(), v.clear();
	p.c[0][tot] = 1;
	for( ll i = 0;i <= cnt;i ++ ) {
		if( i ) v.c[i - 1][i] = ( cnt - i + 1 ) * ( cnt - i + 1 ) % mod;
		v.c[i][i] = ( i * ( cnt - i ) % mod + ( cnt - i ) * ( n - cnt - cnt + i ) % mod ) % mod;
		v.c[i][i] = ( v.c[i][i] + cnt * ( cnt - 1 ) / 2 % mod ) % mod;
		v.c[i][i] = ( v.c[i][i] + ( n - cnt ) * ( n - cnt - 1 ) / 2 % mod ) % mod;
		if( i < cnt ) v.c[i + 1][i] = ( i + 1 ) * ( n - cnt - cnt + i + 1 ) % mod;
	}
	v = qkpow( v, k );
	p = p * v;
	ll ans = p.c[0][cnt], temp = 0;
	for( int i = 0;i <= cnt;i ++ )
		temp = ( temp + p.c[0][i] ) % mod;
	printf( "%lld", ans * qkpow( temp, mod - 2 ) % mod );
	return 0;
}

你可能感兴趣的:(#,普通DP,#,矩阵加速)