这个寒假懒到爆啦~题目做了也都没写题解,今天补一个~这套题今天自己开了虚拟比赛模拟了下,只做出四题,感觉自己弱爆了T T,E题是吃饭的时候突然想到解法的。
传送门:【codeforces】Codeforces Round #291 (Div. 2)
模拟就好了,注意开头数字为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 ;
}
极角排序搞一下,就好啦。我是把弧度小于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 ;
}
这题我是用了一个字典树存下一开始的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 ;
}
首先我们要明确题意(题目简单,就是我读题读了好久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 ;
}
这题只要想到了就很简单。
我们可以假设一个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 ;
}