您的位置:首页 > 其它

bzoj 4000 矩阵快速幂优化DP

2015-06-09 17:26 330 查看
建立矩阵,跑快速幂

/**************************************************************
Problem: 4000
User: idy002
Language: C++
Result: Accepted
Time:32 ms
Memory:836 kb
****************************************************************/

#include <cstdio>
#include <cstring>
#define M 6

struct Matrix {
unsigned v[1<<M][1<<M];
const unsigned *operator[]( int i ) const { return v[i]; }
};

int n, m, p, k, bound;
int attack[3];
int stat[1<<M], id[1<<M], stot;
Matrix base, dest;

void make_unit( Matrix &x ) {
for( int i=0; i<stot; i++ )
for( int j=0; j<stot; j++ )
x.v[i][j] = i==j;
}
Matrix operator*( const Matrix &a, const Matrix &b ) {
Matrix c;
for( int i=0; i<stot; i++ )
for( int j=0; j<stot; j++ ) {
c.v[i][j] = 0;
for( int k=0; k<stot; k++ )
c.v[i][j] += a[i][k]*b[k][j];
}
return c;
}
Matrix mpow( Matrix a, int b ) {
Matrix rt;
for( make_unit(rt); b; b>>=1,a=a*a )
if( b&1 ) rt=rt*a;
return rt;
}
int getarea( int s, int a ) {
int rt = 0;
for( int b=0; b<m; b++ ) {
if( (s>>b)&1 ) {
int aa = a;
if( b<k )
aa >>= k-b;
else
aa <<= b-k;
aa &= bound;
rt |= aa;
}
}
return rt;
}
void build() {
stot = 0;
memset( id, -1, sizeof(id) );
for( int s=0; s<=bound; s++ ) {
if( getarea(s,attack[1])&s ) continue;
stat[stot]=s;
id[s] = stot;
stot++;
}
for( int s1=0; s1<=bound; s1++ ) {
if( id[s1]==-1 ) continue;
for( int s2=0; s2<=bound; s2++ ) {
if( id[s2]==-1 ) continue;
if( getarea(s1,attack[2])&s2 ) continue;
if( getarea(s2,attack[0])&s1 ) continue;
base.v[id[s1]][id[s2]] = 1;
}
}
}
int main() {
scanf( "%d%d%d%d", &n, &m, &p, &k );
bound = (1<<m)-1;
for( int i=0; i<3; i++ )
for( int j=0,o; j<p; j++ ) {
scanf( "%d", &o );
attack[i] = attack[i] | (o<<j);
}
attack[1] ^= 1<<k;
build();
dest = mpow( base, n-1 );
unsigned ans = 0;
for( int i=0; i<stot; i++ )
for( int j=0; j<stot; j++ )
ans += dest[i][j];
printf( "%u\n", ans );
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: