这个寒假懒到爆啦~题目做了也都没写题解,今天补一个~这套题今天自己开了虚拟比赛模拟了下,只做出四题,感觉自己弱爆了T T,E题是吃饭的时候突然想到解法的。
传送门:【codeforces】Codeforces Round #291 (Div. 2)
514A. Chewbaсca and Number
模拟就好了,注意开头数字为9不能变。
#include <cstdio> #include <cstring> #include <cmath> #include <map> #include <iostream> #include <algorithm> using namespace std ; typedef long long LL ; typedef unsigned long long ULL ; #define rep( i , a , b ) for ( int i = ( a ) ; i < ( b ) ; ++ i ) #define For( i , a , b ) for ( int i = ( a ) ; i <= ( b ) ; ++ i ) #define rev( i , a , b ) for ( int i = ( a ) ; i >= ( b ) ; -- i ) #define clr( a , x ) memset ( a , x , sizeof a ) const int MAXN = 30005 ; char s[MAXN] ; void solve () { int n = strlen ( s ) ; rep ( i , 0 , n ) { if ( s[i] >= '5' ) { if ( s[i] == '9' && !i ) continue ; s[i] = 9 - ( s[i] - 48 ) + 48 ; } } rep ( i , 0 , n ) printf ( "%c" , s[i] ) ; printf ( "\n" ) ; } int main () { while ( ~scanf ( "%s" , s ) ) solve () ; return 0 ; }
514B. Han Solo and Lazer Gun
极角排序搞一下,就好啦。我是把弧度小于0的都加上一个pi,但是蠢蠢的忘了0也是要的,wa了N次。
#include <cstdio> #include <cstring> #include <cmath> #include <map> #include <iostream> #include <algorithm> using namespace std ; typedef long long LL ; typedef unsigned long long ULL ; #define rep( i , a , b ) for ( int i = ( a ) ; i < ( b ) ; ++ i ) #define For( i , a , b ) for ( int i = ( a ) ; i <= ( b ) ; ++ i ) #define rev( i , a , b ) for ( int i = ( a ) ; i >= ( b ) ; -- i ) #define clr( a , x ) memset ( a , x , sizeof a ) const int MAXN = 30005 ; const double eps = 1e-10 ; const double pi = acos ( -1.0 ) ; int dcmp ( double x ) { return ( x > eps ) - ( x < -eps ) ; } struct Point { double x , y , r ; bool operator < ( const Point& t ) const { return dcmp ( r - t.r ) < 0 ; } } ; Point p[MAXN] ; int n , x , y ; void solve () { For ( i , 1 , n ) { scanf ( "%lf%lf" , &p[i].x , &p[i].y ) ; p[i].x -= x ; p[i].y -= y ; p[i].r = atan2 ( p[i].y , p[i].x ) ; if ( dcmp ( p[i].r ) <= 0 ) p[i].r += pi ; //printf ( "%.10f\n" , p[i].r ) ; } sort ( p + 1 , p + n + 1 ) ; int ans = 1 ; For ( i , 2 , n ) if ( dcmp ( p[i].r - p[i - 1].r ) ) ++ ans ; printf ( "%d\n" , ans ) ; } int main () { while ( ~scanf ( "%d%d%d" , &n , &x , &y ) ) solve () ; return 0 ; }
514C. Watto and Mechanism
这题我是用了一个字典树存下一开始的n个串,然后m个串在上面模拟一下就好,复杂度么。。我不会算。
#include <cstdio> #include <cstring> #include <cmath> #include <map> #include <iostream> #include <algorithm> using namespace std ; typedef long long LL ; typedef unsigned long long ULL ; #define rep( i , a , b ) for ( int i = ( a ) ; i < ( b ) ; ++ i ) #define For( i , a , b ) for ( int i = ( a ) ; i <= ( b ) ; ++ i ) #define rev( i , a , b ) for ( int i = ( a ) ; i >= ( b ) ; -- i ) #define clr( a , x ) memset ( a , x , sizeof a ) const int MAXN = 600005 ; int next[MAXN][3] ; int end[MAXN] ; char s[MAXN] ; int p ; int n , m ; int newnode () { rep ( i , 0 , 3 ) next[p][i] = 0 ; end[p] = 0 ; return p ++ ; } void insert () { int now = 0 ; for ( int i = 0 ; s[i] ; ++ i ) { int x = s[i] - 'a' ; if ( !next[now][x] ) next[now][x] = newnode () ; now = next[now][x] ; } end[now] = 1 ; } int query ( int cur , int now , int flag ) { if ( flag > 1 ) return 0 ; if ( !s[cur] ) return flag && end[now] ; int x = s[cur] - 'a' ; rep ( i , 0 , 3 ) if ( next[now][i] ) if ( query ( cur + 1 , next[now][i] , flag + ( x != i ) ) ) return 1 ; return 0 ; } void solve () { p = 0 ; newnode () ; rep ( i , 0 , n ) { scanf ( "%s" , s ) ; insert () ; } rep ( i , 0 , m ) { scanf ( "%s" , s ) ; printf ( query ( 0 , 0 , 0 ) ? "YES\n" : "NO\n" ) ; } } int main () { while ( ~scanf ( "%d%d" , &n , &m ) ) solve () ; return 0 ; }
514D. R2D2 and Droid Army
首先我们要明确题意(题目简单,就是我读题读了好久T T),题目要我们求的是一段最长的区间,满足这个区间内M个类型每个类型的最大值相加不超过x。这题呢我一看到就想到二分长度,然后枚举左端点,知道长度且知道了左端点,那么我们就知道了右端点,这样我们就可以用线段树求区间的最大值了。然后M个值加一下看符不符合来调整上下界。
PS:还有个简单的方法,就是用双指针维护滑动窗口,每次窗口向右边扩展一个单位,然后看扩展后是否符合条件,符合的话,和之前得到的答案取个最大值,否则不断从左边抛掉最后一个单位,直到合法为止。是否合法也是用线段树实现。
我这里就贴下我蠢蠢的代码好了。
#include <cstdio> #include <cstring> #include <cmath> #include <map> #include <iostream> #include <algorithm> using namespace std ; typedef long long LL ; typedef unsigned long long ULL ; #define rep( i , a , b ) for ( int i = ( a ) ; i < ( b ) ; ++ i ) #define For( i , a , b ) for ( int i = ( a ) ; i <= ( b ) ; ++ i ) #define rev( i , a , b ) for ( int i = ( a ) ; i >= ( b ) ; -- i ) #define clr( a , x ) memset ( a , x , sizeof a ) #define ls ( o << 1 ) #define rs ( o << 1 | 1 ) #define lson ls , l , m #define rson rs , m + 1 , r #define root 1 , 1 , n #define mid ( ( l + r ) >> 1 ) const int MAXN = 100005 ; int maxv[5][MAXN << 2] ; int ans[5] ; int n , M , k ; void build ( int o , int l , int r ) { if ( l == r ) { rep ( i , 0 , M ) scanf ( "%d" , &maxv[i][o] ) ; return ; } int m = mid ; build ( lson ) ; build ( rson ) ; rep ( i , 0 , M ) maxv[i][o] = max ( maxv[i][ls] , maxv[i][rs] ) ; } void query ( int L , int R , int o , int l , int r ) { if ( L <= l && r <= R ) { rep ( i , 0 , M ) ans[i] = max ( ans[i] , maxv[i][o] ) ; return ; } int m = mid ; if ( L <= m ) query ( L , R , lson ) ; if ( m < R ) query ( L , R , rson ) ; } int check ( int m ) { if ( !m ) { clr ( ans , 0 ) ; return 0 ; } For ( i , 1 , n - m + 1 ) { int l = i , r = i + m - 1 ; clr ( ans , 0 ) ; query ( l , r , root ) ; int sum = 0 ; rep ( i , 0 , M ) sum += ans[i] ; if ( sum <= k ) return 1 ; } return 0 ; } void solve () { int l = 0 , r = n ; build ( root ) ; while ( l < r ) { int m = ( l + r + 1 ) >> 1 ; if ( check ( m ) ) l = m ; else r = m - 1 ; } check ( l ) ; rep ( i , 0 , M ) printf ( "%d%c" , ans[i] , i < M - 1 ? ' ' : '\n' ) ; } int main () { while ( ~scanf ( "%d%d%d" , &n , &M , &k ) ) solve () ; return 0 ; }
514E. Darth Vader and Tree
这题只要想到了就很简单。
我们可以假设一个dp[i]表示到根的距离为i的方案数,那么我们可以发现如果我们有长度为a、b、c的三条边,那么dp[i] = dp[i - a] + dp[i - b] + dp[i - c]。由于长度最多只有100种且最大是100,那么我们就可以用上矩阵快速幂啦!顺便用矩阵快速幂求dp[0]+dp[1]+dp[2]+......+dp[x]就好了。
#include <cstdio> #include <cstring> #include <cmath> #include <map> #include <iostream> #include <algorithm> using namespace std ; typedef long long LL ; typedef unsigned long long ULL ; #define rep( i , a , b ) for ( int i = ( a ) ; i < ( b ) ; ++ i ) #define For( i , a , b ) for ( int i = ( a ) ; i <= ( b ) ; ++ i ) #define rev( i , a , b ) for ( int i = ( a ) ; i >= ( b ) ; -- i ) #define clr( a , x ) memset ( a , x , sizeof a ) #define ls ( o << 1 ) #define rs ( o << 1 | 1 ) #define lson ls , l , m #define rson rs , m + 1 , r #define root 1 , 1 , n #define mid ( ( l + r ) >> 1 ) const int MAXN = 105 ; const int mod = 1000000007 ; struct Matrix { int mat[MAXN][MAXN] ; int n ; Matrix () {} Matrix ( int n ) : n ( n ) { clr ( mat , 0 ) ; } void eye () { rep ( i , 0 , n ) rep ( j , 0 , n ) mat[i][j] = i == j ; } Matrix operator * ( const Matrix& b ) const { Matrix c ( n ) ; rep ( i , 0 , n ) rep ( j , 0 , n ) rep ( k , 0 , n ) c.mat[i][j] = ( c.mat[i][j] + ( LL ) mat[i][k] * b.mat[k][j] ) % mod ; return c ; } Matrix operator ^ ( int k ) const { Matrix res ( n ) , tmp = *this ; res.eye () ; while ( k ) { if ( k & 1 ) res = res * tmp ; tmp = tmp * tmp ; k >>= 1 ; } return res ; } } ; int n , m ; void solve () { int x ; Matrix A ( 101 ) ; A.mat[0][0] = A.mat[0][1] = 1 ; while ( n -- ) { scanf ( "%d" , &x ) ; ++ A.mat[1][x] ; } For ( i , 2 , 100 ) A.mat[i][i - 1] = 1 ; Matrix ans = A ^ ( m + 1 ) ; printf ( "%d\n" , ans.mat[0][1] ) ; } int main () { while ( ~scanf ( "%d%d" , &n , &m ) ) solve () ; return 0 ; }