CF,AT水题题解
Pre
本弱实在是太弱了,身边的大佬们切题如喝水,而我昨天A+B做了快一个小时。。。
写一下简要的题意和收获,暂时只打算改ABCD,也许能力强一点(根本不会发生的事)之后会改EF。
#CF Round 740
A
纯模拟
B
算出一个人需要反转几次才能赢,然后枚举他赢得次数。
因为每次赢都可以和一次输反转加两次break
C
二分答案,先二分计算出来进入每个山洞需要的最小体力。
然后在二分答案,优先选择最小体力最小的山洞进入。
D
貌似这题还行,大佬都说是水题。
D1 可以差分处理第一种+整除分块处理第二种(\(n \sqrt n\))
D2 比较巧妙不用这个点去刷新别人,而是对于每个点看他从谁转移过来,配合一个前缀和,枚举调和级数。(\(n ln n\))
\(\lfloor \frac{a}{b} \rfloor=c\)的数对,对于每一个\(c\),可以直接枚举\(b\)。
这样,最后一个 \(\lfloor \frac{a}{b} \rfloor !=c\)的\(a\)必定是 \((c+1)*b\)。
所以,直接把 \([c*b,(c+1)*b-1]\)的前缀和加到答案就行了。
整除分块变调和枚举。
#CF Round 741
A
假设模数是\(x\) ,答案就是 \(min(r-x,x-1)\)。
发现是两个一次函数取min,是个单峰且单调段都线性变化。
所以直接看峰点是否在范围内,否则直接把左/右端点当成x
B
看起来很唬人,然而不难。
如果个位中出现了1/4/6/8/9,那么直接输出就是合法方案。
否则,如果有一个位上面的数出现了两次或以上,我们可以11乘这个数。
如果都没判走,那么这个k<=4,直接状压就行了。
推性质带走合法状态从而枚举。
C
考场太困没想出来(菜)
够造一种合法方案,首先如果序列里面有0,那可以操作。
他在前半段,我们可以连上后半段输出两个相等的数(加前导0)
他在后半段,可以构造出两个数为二倍关系。
所以序列里全剩1了,这样也有很多种构造
直接输出两个全等的串(1~(n-1),2~n)。
或者构造(x*(x+2))也可以。
第二种就是先把和他一样长的一段0复制在后面,在加上他自己
111-> 111000 -> 111111
D
太菜还不会做,太废还不想看题解。
#CF Deltix Round
A
分情况讨论即可
B
考场上让这题整自闭了,就一个沙雕地方打错了。
但本质还是对自己的不自信,如果对排序之后用相减的绝对值加起来很有信心的话,那么看出来别的地方大错还是很有可能的。
但是现在想想确实不知所错,当时总认为交换会影响其他的。
影响确实有,就是把abcdef -> bcdefa
这就是通过交换把一个数移到一个位置的本质,影响就是会把路径上排好序的部分打乱。
所以我们从两边开始考虑,如果两边无序,先把两边的移动到正确的为位置,这样不会对其他造成影响。
如果两边有序,那么把两边去掉,就变成了一个子问题。
举个例子,11100
左边已经有序,所以交换使右边有序 11001
左右都有序,去掉左右,变成了 100 的子问题
右边已经有序,通过交换使左边有序,那就是010。
当让可以记作结论,把若干个数从原位置移动到想要的位置,直接排序把差的绝对值相加就行了。
C
考场上会做,但是没打。
每个区间记录一个pair代表缺几个左右括号,然后 \(n^2\) 枚举每个区间就行了。
D
考场上是想着不能确定整个序列有spj来着。
没想到有个结论 (a+b)= (a|b) + (a&b)
分情况讨论一下就可以证明,只考虑每一位。
如果两个数都是1,那么与是1,或是1,正确
如果一个1一个0,那么与是0,或是1,正确
如果是两个0,那么与或也都是0,正确
所以上述结论是正确的。
#AT ABC216
A,B,C
简单的模拟
D
按照题意用栈模拟一下就行了。
E
还是排序模拟一下,每次让变量和下一个变量相同就好了。
F
考虑每个位置是最大值的情况。
不难写出一份暴力背包代码。
code
#include <cstdio>
#include <cstring>
#include <assert.h>
#include <algorithm>
#define R register int
#define scanf Ruusupuu = scanf
#define freopen rsp_5u = freopen
#define fre(x) freopen( #x".in" , "r" , stdin ) , freopen( #x".out" , "w" , stdout )
int Ruusupuu ;
FILE * rsp_5u ;
using namespace std ;
typedef long long L ;
typedef double D ;
const int N = 5e3 + 10 ;
const int P = 998244353 ;
inline int read(){
int w = 0 ; bool fg = 0 ; char ch = getchar() ;
while( ch < '0' || ch > '9' ) fg |= ( ch == '-' ) , ch = getchar() ;
while( ch >= '0' && ch <= '9' ) w = ( w << 1 ) + ( w << 3 ) + ( ch ^ 48 ) , ch = getchar() ;
return fg ? -w : w ;
}
int n , ans , a [N] , b [N] , f [N] ;
inline int A( int a , int b ){ return ( a + b ) >= P ? ( a + b - P ) : ( a + b ) ; }
inline int E( int a , int b ){ return ( a - b ) < 0 ? ( a - b + P ) : ( a - b ) ; }
void sc(){
n = read() ;
for( R i = 1 ; i <= n ; i ++ ) a [i] = read() ;
for( R i = 1 ; i <= n ; i ++ ) b [i] = read() ;
}
void work(){
for( R i = 1 ; i <= n ; i ++ ) if( a [i] >= b [i] ) {
memset( f , 0 , sizeof( f ) ) , f [0] = 1 ;
for( R j = 1 ; j <= n ; j ++ ) if( i != j && a [j] <= a [i] )
for( R k = N - 10 ; k >= b [j] ; k -- ) f [k] = A( f [k] , f [k - b [j]] ) ;
for( R j = 0 ; j <= a [i] - b [i] ; j ++ ) ans = A( ans , f [j] ) ;
} printf( "%d\n" , ans ) ;
}
signed main(){
sc() ;
work() ;
return 0 ;
}
但是是 \(n^3\) 的,所以排个序前缀和优化以下就行了。
code
#include <cstdio>
#include <cstring>
#include <assert.h>
#include <algorithm>
#define R register int
#define scanf Ruusupuu = scanf
#define freopen rsp_5u = freopen
#define fre(x) freopen( #x".in" , "r" , stdin ) , freopen( #x".out" , "w" , stdout )
int Ruusupuu ;
FILE * rsp_5u ;
using namespace std ;
typedef long long L ;
typedef double D ;
const int N = 5e3 + 10 ;
const int P = 998244353 ;
inline int read(){
int w = 0 ; bool fg = 0 ; char ch = getchar() ;
while( ch < '0' || ch > '9' ) fg |= ( ch == '-' ) , ch = getchar() ;
while( ch >= '0' && ch <= '9' ) w = ( w << 1 ) + ( w << 3 ) + ( ch ^ 48 ) , ch = getchar() ;
return fg ? -w : w ;
}
int n , ans , a [N] , b [N] , f [N][N] ;
struct T{ int a , b ; } p [N] ;
inline bool cmp( T a , T b ){ return a.a < b.a ; }
inline int A( int a , int b ){ return ( a + b ) >= P ? ( a + b - P ) : ( a + b ) ; }
inline int E( int a , int b ){ return ( a - b ) < 0 ? ( a - b + P ) : ( a - b ) ; }
void sc(){
n = read() , f [0][0] = 1 ;
for( R i = 1 ; i <= n ; i ++ ) p [i].a = read() ;
for( R i = 1 ; i <= n ; i ++ ) p [i].b = read() ;
sort( p + 1 , p + 1 + n , cmp ) ;
for( R i = 1 ; i <= n ; i ++ ) a [i] = p [i].a , b [i] = p [i].b ;//, printf( "%d %d\n" , a [i] , b [i] ) ;
for( R i = 1 ; i <= n ; i ++ ) for( R j = N - 10 ; j >= 0 ; j -- )
if( j >= b [i] ) f [i][j] = A( f [i - 1][j] , f [i - 1][j - b [i]] ) ;
else f [i][j] = A( f [i][j] , f [i - 1][j] ) ;
for( R i = 0 ; i <= n ; i ++ ) for( R j = 1 ; j <= N - 10 ; j ++ )
f [i][j] = A( f [i][j] , f [i][j - 1] ) ;
}
void work(){
for( R i = 1 ; i <= n ; i ++ ) if( a [i] >= b [i] ) // printf( "%d\n" , f [i - 1][a [i] - b [i]] ) ,
ans = A( ans , f [i - 1][a [i] - b [i]] ) ;
printf( "%d\n" , ans ) ;
}
signed main(){
sc() ;
work() ;
return 0 ;
}

浙公网安备 33010602011771号