对于这道题,我们已知的是当 M = 2 时,这就是我们已知的【汉诺塔问题】。那么我们的思路就可以是用解决汉诺塔问题的思路来解决这道题。
# include <cstdio># include <cstring># include <iostream># include <algorithm>usingnamespacestd ;
# define Name "hanoi"# define LL long long
LL dp [70] [70] ;
int main () {
freopen ( Name ".in" , "r" , stdin ) ;
freopen ( Name ".out" , "w" , stdout ) ;
memset ( dp , 0x3f , sizeof dp ) ;
int n , m ;
scanf ( "%d%d" , & n , & m ) ;
dp [1] [3] = 1 ;
for ( int i = 2 ; i <= n ; ++ i )
dp [i] [2] = 0 ,
dp [i] [3] = ( 1LL << i ) - 1LL ;
for ( int i = 3 ; i <= m ; ++ i )
dp [1] [i] = 1 ;
for ( int i = 2 ; i <= n ; ++ i )
for ( int j = 4 ; j <= m ; ++ j )
for ( int r = 1 ; r < i ; ++ r )
dp [i] [j] = min ( dp [i] [j] , dp [ i - r ] [j] * 2 + dp [r] [ j - 1 ] ) ;
printf ( "%lld" , dp [n] [m] ) ;
return0 ;
}
T2
水
# include <vector># include <cstdio># include <cstring># include <iostream># include <algorithm># define LL long long# define Name "rank" usingnamespacestd;
constint N = 2e5 + 10 ;
char ch [N] ;
struct P {
int len , rk ;
booloperator < ( const P & x ) const {
return rk < x.rk ;
}
} a [N] ;
int rk [N] ;
int n ;
int id ( int len ) {
return n - len + 1 ;
}
int main () {
freopen ( Name ".in" , "r" , stdin ) ;
freopen ( Name ".out" , "w" , stdout ) ;
memset ( ch , '\0' , sizeof ch ) ;
scanf ( "%d" , & n ) ;
for ( int i = 1 ; i <= n ; ++ i ) {
scanf ( "%d" , & a [i].rk ) ;
rk [ n - i + 1 ] = a [i].rk ;
a [i].len = n - i + 1 ;
}
sort ( a + 1 , a + 1 + n ) ;
for ( int i = 1 ; i < n ; ++ i ) {
int l1 = a [i].len - 1 ;
int l2 = a [ i + 1 ].len - 1 ;
if ( rk [l1] > rk [l2] ) {
if ( ch [ id ( l1 + 1 ) ] == '\0' )
ch [ id ( l1 + 1 ) ] = 'a' ;
if ( ch [ id ( l2 + 1 ) ] == '\0' )
ch [ id ( l2 + 1 ) ] = ch [ id ( l1 + 1 ) ] + 1 ;
if ( ch [ id ( l2 + 1 ) ] > ch [ id ( l1 + 1 ) ] + 1 ) {
printf ( "-1" ) ;
return0 ;
}
} else {
if ( ch [ id ( l1 + 1 ) ] == '\0' )
ch [ id ( l1 + 1 ) ] = 'a' ;
if ( ch [ id ( l2 + 1 ) ] == '\0' )
ch [ id ( l2 + 1 ) ] = ch [ id ( l1 + 1 ) ] ;
if ( ch [ id ( l2 + 1 ) ] != ch [ id ( l1 + 1 ) ] ) {
printf ( "-1" ) ;
return0 ;
}
}
}
for ( int i = 1 ; i <= n ; ++ i ) {
if ( ch [i] < 'a' || ch [i] > 'z' ) {
printf ( "-1" ) ;
return0 ;
}
}
for ( int i = 1 ; i <= n ; ++ i )
printf ( "%c" , ch [i] ) ;
return0 ;
}
T3
期望概率神题:
# include <vector># include <cstdio># include <cstring># include <iostream># include <algorithm># define LL long long# define Name ""usingnamespacestd ;
constint N = 2e5 + 10 ;
constint P = 17 ;
const LL Mod = 1e9 + 7 ;
vector <int> G [N] ;
int sz [N] , dep [N] , fa [N] [20] ;
int n , q ;
LL f [N] , g [N] , pw [30] ;
int LCA ( int u , int v ) {
if ( dep [u] < dep [v] ) swap ( u , v ) ;
int t = dep [u] - dep [v] ;
for ( int i = 0 ; pw [i] <= t ; ++ i )
if ( pw [i] & t ) u = fa [u] [i] ;
for ( int i = P ; i >= 0 ; -- i ) {
if ( fa [u] [i] != fa [v] [i] ) {
u = fa [u] [i] ;
v = fa [v] [i] ;
}
}
if ( u == v ) return u ;
return fa [u] [0] ;
}
void dfs ( int u , int fat ) {
fa [u] [0] = fat ;
for ( int i = 1 ; i <= P ; ++ i )
fa [u] [i] = fa [ fa [u] [ i - 1 ] ] [ i - 1 ] ;
sz [u] = 1 ;
for ( int i = 0 ; i < G [u].size () ; ++ i ) {
int v = G [u] [i] ;
if ( v == fat ) continue ;
dep [v] = dep [u] + 1 ;
dfs ( v , u ) ;
sz [u] += sz [v] ;
}
}
void dfs_da ( int u , int fat ) {
for ( int i = 0 ; i < G [u].size () ; ++ i ){
int v = G [u] [i] ;
if ( v == fat ) continue ;
f [v] = ( LL ) ( f [u] + 2LL * ( n - sz [v] ) - 1LL ) % Mod ;
g [v] = ( LL ) ( g [u] + 2LL * sz [v] - 1LL ) % Mod;
dfs_da ( v , u ) ;
}
}
int main () {
freopen ("tree.in", "r", stdin);
freopen ("tree.out", "w", stdout);
pw [0] = 1 ;
for ( int i = 1 ; i <= P ; ++ i ) pw [i] = pw [ i - 1 ] * 2 ;
scanf ( "%d%d" , & n , & q ) ;
for ( int i = 1 ; i < n ; ++ i ) {
int x , y ;
scanf ( "%d%d" , & x , & y ) ;
G [x].push_back ( y ) ;
G [y].push_back ( x ) ;
}
dfs ( 1 , 1 ) ;
dfs_da ( 1 , 1 ) ;
while ( q -- ) {
int u , v ;
scanf ( "%d%d" , & u , & v ) ;
int x = LCA ( u , v ) ;
// printf ( ">%d %d %d \n" , u , v , x ) ;printf ( "%lld\n" , ( ( f [v] - f [x] + g [u] - g [x] ) % Mod + Mod ) % Mod ) ;
}
return0 ;
}