生活随笔
收集整理的這篇文章主要介紹了
2021百度之星程序设计大赛-初赛一部分题目总结
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
部分題目 1001迷失 1003鴿子 1004萌新 1006毒瘤數(shù)據(jù)結(jié)構(gòu)題 1008獵人殺
1001迷失
題目意思是要從11 1 號(hào)島嶼經(jīng)過(guò)kk k 條路徑到達(dá)nn n 號(hào)島嶼的概率,里面提出了一個(gè)附魔橋和普通橋的概念,經(jīng)過(guò)附魔橋身上如果有附魔則附魔消失,如果沒(méi)有附魔則被標(biāo)記;到達(dá)nn n 號(hào)島嶼的時(shí)候,身上必須有附魔才能成功逃離,問(wèn)成功逃離的概率 解決這個(gè)問(wèn)題需要幾個(gè)知識(shí)點(diǎn)
鄰接矩陣k次方的結(jié)論
如果從ii i 到jj j 有路徑,則設(shè)a[i][j]=1a[i][j]=1 a [ i ] [ j ] = 1 ,則矩陣ak[i][j]a^k[i][j] a k [ i ] [ j ] 表示從ii i 到jj j 經(jīng)過(guò)kk k 條路徑的通路總數(shù)
拆點(diǎn)法
將每一個(gè)點(diǎn)拆成兩個(gè)點(diǎn),分別為有附魔的和沒(méi)附魔的,可以分別表示為ii i 和i+ni+n i + n ,見下圖 上面表示帶附魔的,如果ii i 經(jīng)過(guò)一條普通邊,只需要在同側(cè)連邊;如果經(jīng)過(guò)附魔邊,則連向另外一側(cè) 這樣以后只需要填充鄰接矩陣先計(jì)算出所有點(diǎn)的度數(shù),接下來(lái)根據(jù)每個(gè)點(diǎn)的的度數(shù)計(jì)算對(duì)模的逆元,之后進(jìn)行矩陣快速冪計(jì)算即可
# include <iostream>
# include <cstring>
# include <algorithm>
# include <queue>
# include <stack>
# include <vector>
# include <cmath>
# include <cstdio>
# include <map>
using namespace std
;
typedef long long ll
;
const int MAXN
= 333 ;
const ll MOD
= 998244353 ;
inline int read ( ) { int x
= 0 , f
= 1 ; char c
= getchar ( ) ; while ( c
< '0' || c
> '9' ) { if ( c
== '-' ) f
= - 1 ; c
= getchar ( ) ; } while ( c
>= '0' && c
<= '9' ) { x
= ( x
<< 1 ) + ( x
<< 3 ) + ( c
^ 48 ) ; c
= getchar ( ) ; } return x
* f
;
}
struct Matrix { ll m
[ MAXN
] [ MAXN
] ; Matrix ( ) { memset ( m
, 0 , sizeof m
) ; }
} ;
Matrix
mul ( Matrix a
, Matrix b
, int n
) { Matrix ans
; for ( int i
= 1 ; i
<= n
; i
++ ) { for ( int j
= 1 ; j
<= n
; j
++ ) { for ( int k
= 1 ; k
<= n
; k
++ ) { ans
. m
[ i
] [ j
] = ( ans
. m
[ i
] [ j
] + a
. m
[ i
] [ k
] * b
. m
[ k
] [ j
] ) % MOD
; } } } return ans
;
}
Matrix
fastpow ( Matrix base
, int power
, int n
) { Matrix ans
; for ( int i
= 1 ; i
<= n
; i
++ ) ans
. m
[ i
] [ i
] = 1 ; while ( power
) { if ( power
& 1 ) ans
= mul ( ans
, base
, n
) ; base
= mul ( base
, base
, n
) ; power
>>= 1 ; } return ans
;
}
void extend_gcd ( ll a
, ll b
, ll
& x
, ll
& y
) { if ( b
== 0 ) { x
= 1 ; y
= 0 ; return ; } extend_gcd ( b
, a
% b
, x
, y
) ; ll tmp
= x
; x
= y
; y
= tmp
- a
/ b
* y
;
}
ll
inverse_mod ( ll y
, ll p
) { ll x
, m
; extend_gcd ( y
, p
, x
, m
) ; return ( p
+ x
% p
) % p
;
}
int degree
[ MAXN
] ;
ll inv
[ MAXN
] ;
int main ( ) { int t
, n
, m
, k
, u
, v
, w
; t
= read ( ) ; while ( t
-- ) { n
= read ( ) ; m
= read ( ) ; k
= read ( ) ; Matrix edge
, mp
; for ( int i
= 0 ; i
< m
; i
++ ) { u
= read ( ) ; v
= read ( ) ; w
= read ( ) ; edge
. m
[ u
] [ v
] = w
+ 1 ; edge
. m
[ v
] [ u
] = w
+ 1 ; } for ( int i
= 1 ; i
<= n
; i
++ ) { for ( int j
= 1 ; j
<= n
; j
++ ) { if ( edge
. m
[ i
] [ j
] == 2 ) { ++ degree
[ i
] ; ++ degree
[ j
] ; ++ degree
[ i
+ n
] ; ++ degree
[ j
+ n
] ; } else if ( edge
. m
[ i
] [ j
] == 1 ) { ++ degree
[ i
] ; ++ degree
[ j
] ; ++ degree
[ i
+ n
] ; ++ degree
[ j
+ n
] ; } } } for ( int i
= 1 ; i
<= n
; i
++ ) { degree
[ i
] >>= 1 ; inv
[ i
] = inverse_mod ( degree
[ i
] , MOD
) ; degree
[ i
] = degree
[ i
+ n
] = 0 ; } for ( int i
= 1 ; i
<= n
; i
++ ) { for ( int j
= 1 ; j
<= n
; j
++ ) { if ( edge
. m
[ i
] [ j
] == 1 ) { mp
. m
[ i
] [ j
] = inv
[ i
] ; mp
. m
[ i
+ n
] [ j
+ n
] = inv
[ i
] ; } else if ( edge
. m
[ i
] [ j
] == 2 ) { mp
. m
[ i
+ n
] [ j
] = inv
[ i
] ; mp
. m
[ i
] [ j
+ n
] = inv
[ i
] ; } } } mp
= fastpow ( mp
, k
, 2 * n
) ; cout
<< mp
. m
[ 1 ] [ 2 * n
] << '\n' ; } return 0 ;
}
樣例沒(méi)問(wèn)題不過(guò)交在HDU上面返回TLE,標(biāo)程就是這個(gè)思路,可能是評(píng)測(cè)機(jī)的問(wèn)題吧,我用榜11 1 的代碼交了也是TLE,聽說(shuō)用矩陣計(jì)算這里用更高級(jí)的辦法能把時(shí)間優(yōu)化到500ms500ms 5 0 0 m s 以下??
1003鴿子
設(shè)dp[i]dp[i] d p [ i ] 表示當(dāng)前操作壞的電腦位置在ii i 的最少操作次數(shù),那么因?yàn)楫?dāng)前操作是交換ii i 和jj j ,所以有dp[i]=min(dp[i]+1,dp[j])dp[i]=min(dp[i]+1,dp[j]) d p [ i ] = m i n ( d p [ i ] + 1 , d p [ j ] ) dp[j]=min(dp[j]+1,dp[i])dp[j]=min(dp[j]+1,dp[i]) d p [ j ] = m i n ( d p [ j ] + 1 , d p [ i ] ) 很容易理解,注意更新不要覆蓋
# include <iostream>
# include <cstring>
# include <algorithm>
# include <queue>
# include <stack>
# include <vector>
# include <cmath>
# include <cstdio>
# include <map>
using namespace std
;
typedef long long ll
;
const int MAXN
= 2e5 + 100 ;
const int INF
= 0x3f3f3f3f ;
int Data
[ MAXN
] ;
int dp
[ MAXN
] ;
int main ( ) { ios
:: sync_with_stdio ( false ) ; int t
, n
, m
, k
, u
, v
; cin
>> t
; while ( t
-- ) { cin
>> n
>> m
>> k
; memset ( dp
, 0x3f , sizeof dp
) ; dp
[ k
] = 0 ; for ( int i
= 1 ; i
<= m
; i
++ ) { cin
>> u
>> v
; int a
= dp
[ u
] ; int b
= dp
[ v
] ; dp
[ v
] = min ( b
+ 1 , a
) ; dp
[ u
] = min ( a
+ 1 , b
) ; } for ( int i
= 1 ; i
<= n
; i
++ ) { if ( i
!= 1 ) cout
<< ' ' ; cout
<< ( dp
[ i
] == INF
? - 1 : dp
[ i
] ) ; } cout
<< '\n' ; } return 0 ;
}
1004萌新
已知aa a 和bb b 模cc c 同余,給定aa a 和bb b ,讓求cc c 的最小和最大值,滿足c?1>0c-1\gt0 c ? 1 > 0 且c≤max(a,b)c\leq max(a,b) c ≤ m a x ( a , b ) 現(xiàn)在假定a>ba\gt b a > b ,顯然有a?b=kca-b=kc a ? b = k c ,那么c最大時(shí)候顯然是kckc k c 也就是a?ba-b a ? b ,但是這里需要注意兩種特殊情況分別是a?b=1a-b=1 a ? b = 1 和a?b=0a-b=0 a ? b = 0 ;當(dāng)求c最小的時(shí)候只需要枚舉a?ba-b a ? b 的每個(gè)因子,找到最小即可,但是需要注意特判a=1,b=1a=1,b=1 a = 1 , b = 1 的兩種情況
# include <iostream>
# include <cstring>
# include <algorithm>
# include <queue>
# include <stack>
# include <vector>
# include <cmath>
# include <cstdio>
# include <map>
using namespace std
;
typedef long long ll
;
const int MAXN
= 2e5 + 100 ;
const int INF
= 0x3f3f3f3f ;
int Data
[ MAXN
] ;
int main ( ) { ios
:: sync_with_stdio ( false ) ; int t
; ll a
, b
; cin
>> t
; while ( t
-- ) { cin
>> a
>> b
; if ( a
< b
) swap ( a
, b
) ; ll c
= a
- b
; if ( ( a
== 1 && b
== 1 ) || c
== 1 ) { cout
<< - 1 << " " << - 1 << '\n' ; continue ; } if ( a
== b
) { cout
<< 2 << " " << a
<< '\n' ; continue ; } int f
= 0 ; for ( ll i
= 2 ; i
* i
<= c
; i
++ ) { if ( c
% i
== 0 ) { cout
<< i
<< " " ; f
= 1 ; break ; } } if ( f
) cout
<< c
<< '\n' ; else cout
<< c
<< ' ' << c
<< '\n' ; } return 0 ;
}
1006毒瘤數(shù)據(jù)結(jié)構(gòu)題
考察思維,用兩個(gè)指針維護(hù)最左邊的兩個(gè)0,對(duì)于操作1,如果修改了第一個(gè)0,則更新最左邊兩個(gè)0的位置,如果修改了第二個(gè)0,則更新第二個(gè)0的位置,其他情況正常標(biāo)記;對(duì)于操作2,如果查詢到第一個(gè)0,那么答案為第二個(gè)0的位置,其他情況答案都為第一個(gè)0的位置 在HDU上必須用超級(jí)快讀才能過(guò)得了
# include <iostream>
# include <algorithm>
# include <cstring>
# include <cstdio>
# include <vector>
# include <cmath>
# include <queue>
# include <stack>
# include <map>
# include <iomanip>
using namespace std
;
typedef long long ll
;
typedef unsigned long long ull
;
const int INF
= 0x3f3f3f3f ;
const int MAXN
= 1e7 + 100 ;
const double eps
= 1e-6 ;
int vis
[ MAXN
] ;
inline int read ( ) { int x
= 0 , f
= 1 ; char c
= getchar ( ) ; while ( c
< '0' || c
> '9' ) { if ( c
== '-' ) f
= - 1 ; c
= getchar ( ) ; } while ( c
>= '0' && c
<= '9' ) { x
= ( x
<< 1 ) + ( x
<< 3 ) + ( c
^ 48 ) ; c
= getchar ( ) ; } return x
* f
;
}
namespace IO
{ inline char nc ( ) { static char buf
[ 100000 ] , * p1
= buf
, * p2
= buf
; return p1
== p2
&& ( p2
= ( p1
= buf
) + fread ( buf
, 1 , 100000 , stdin ) , p1
== p2
) ? EOF : * p1
++ ; } template < typename T > inline T
read ( ) { char ch
= nc ( ) ; T sum
= 0 ; while ( ch
< '0' || ch
> '9' ) { ch
= nc ( ) ; if ( ch
== EOF ) return EOF ; } while ( ch
>= '0' && ch
<= '9' ) { sum
= ( sum
<< 1 ) + ( sum
<< 3 ) + ( ch
^ 48 ) ; ch
= nc ( ) ; if ( ch
== EOF ) return EOF ; } return sum
; }
}
int main ( ) { ios
:: sync_with_stdio ( false ) ; int n
, a
, b
; n
= IO
:: read
< int > ( ) ; int x
, y
; x
= 1 ; y
= 2 ; for ( int i
= 0 ; i
< n
; i
++ ) { a
= IO
:: read
< int > ( ) ; b
= IO
:: read
< int > ( ) ; if ( a
== 1 ) { vis
[ b
] = 1 ; if ( b
== y
) { while ( vis
[ y
] ) ++ y
; } else if ( b
== x
) { x
= y
; ++ y
; while ( vis
[ y
] ) ++ y
; } } else { if ( b
== x
) printf ( "%d\n" , y
) ; else printf ( "%d\n" , x
) ; } } return 0 ;
}
1008獵人殺
狼人先殺人(也可能自刀),之后獵人開槍互相殺,直到殺死狼或者剩下人數(shù)不大于2 暴力模擬即可
# include <iostream>
# include <algorithm>
# include <cstring>
# include <cstdio>
# include <vector>
# include <cmath>
# include <queue>
# include <stack>
# include <map>
# include <iomanip>
using namespace std
;
typedef long long ll
;
typedef unsigned long long ull
;
const int INF
= 0x3f3f3f3f ;
const int MAXN
= 1e6 + 100 ;
const double eps
= 1e-6 ;
int main ( ) { ios
:: sync_with_stdio ( false ) ; cin
. tie ( 0 ) ; cout
. tie ( 0 ) ; int t
, n
, x
; cin
>> t
; while ( t
-- ) { cin
>> n
; int id
= - 1 ; for ( int i
= 1 ; i
<= n
; i
++ ) { cin
>> x
; if ( x
== 1 ) id
= i
; } vector
< vector
< int > > vs ( n
+ 5 ) ; vector
< int > vis ( n
+ 5 ) ; for ( int i
= 1 ; i
<= n
; i
++ ) { for ( int j
= 1 ; j
<= n
; j
++ ) { cin
>> x
; vs
[ i
] . push_back ( x
) ; } } int ok
= 0 ; int now
= vs
[ id
] [ 0 ] ; int res
= n
- 1 ; vis
[ now
] = 1 ; if ( now
== id
) { ok
= 2 ; } else if ( res
<= 2 ) { ok
= 1 ; } else { while ( 1 ) { if ( ok
) break ; for ( int i
= 0 ; i
< vs
[ now
] . size ( ) ; i
++ ) { int to
= vs
[ now
] [ i
] ; if ( vis
[ to
] || to
== now
) continue ; vis
[ to
] = 1 ; now
= to
; -- res
; if ( now
== id
) { ok
= 2 ; } else if ( res
<= 2 ) { ok
= 1 ; } break ; } } } cout
<< ( ok
== 1 ? "langren" : "lieren" ) << '\n' ; } return 0 ;
}
總結(jié)
以上是生活随笔 為你收集整理的2021百度之星程序设计大赛-初赛一部分题目总结 的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
如果覺(jué)得生活随笔 網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔 推薦給好友。