【codeforces】Codeforces Round #291 (Div. 2) 题解

这个寒假懒到爆啦~题目做了也都没写题解,今天补一个~这套题今天自己开了虚拟比赛模拟了下,只做出四题,感觉自己弱爆了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 ;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值