Loading

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 ;
}
posted @ 2021-08-28 07:09  Soresen  阅读(94)  评论(0)    收藏  举报