目录
A. JB Loves Math
思路:
a b
要使a = b
则使b-a = 0
1.b-a = 正偶
1.1 (b-a)/2为奇数 则b-a+(b-a)/2+(b-a)/2 = 0
1.2 (b-a)/2为偶数 b-a + (b-a+1)+(b-a+1) - (b-a+2)= 0
2.a-b = 正奇
a-b - (a-b+1) + 1 = 0
3.其他情况比较简单就不讨论了
#include<bits/stdc++.h>
using namespace std ;
const int maxn = 1e3 + 10 ;
const int inf = 0x3f3f3f3f ;
void deal(){
int a , b ; cin >> a >> b ;
if(a == b)cout << 0 << endl ;
else if(a > b){
if((a-b) % 2 == 0){
cout << 1 << endl ;
}else{
cout << 2 << endl ;
}
}else{
if((b - a) % 2 == 1){
cout << 1 << endl ;
}else{
if((b-a)/2 % 2 == 1)cout << 2 << endl ;
else cout << 3 << endl ;
}
}
}
int main(){
int t ; cin >> t ;
while(t--)deal() ;
return 0 ;
}
B.JB Loves Comma
#include<bits/stdc++.h>
using namespace std ;
const int maxn = 1e3 + 10 ;
const int inf = 0x3f3f3f3f ;
void deal(){
string s ; cin >> s ;
for(int i = 0 ; i < s.size() ; i++){
cout << s[i] ;
if(i >= 2 && s.substr(i-2 , 3) == "cjb"){
cout << "," ;
}
}
}
int main(){
deal() ;
return 0 ;
}
C. JB Wants to Earn Big Money
#include<bits/stdc++.h>
using namespace std ;
typedef long long ll ;
const int maxn = 1e5 + 10 ;
const int inf = 0x3f3f3f3f ;
void deal(){
int n , m , x , ans = 0 ; cin >> n >> m >> x ;
for(int i = 0 ; i < n ; i++){
int v ; cin >> v ;
if(v >= x)ans++ ;
}
for(int i = 0 ; i < m ; i++){
int v ; cin >> v ;
if(v <= x)ans++ ;
}
cout << ans << endl ;
}
int main(){
deal() ;
return 0 ;
}
L. Candy Machine
思路:假设最终选择的集合的平均数不超过 k。 为使平均数不超过 k,应将 ≤ k 的数全部选入,然后贪心选 择 > k 的部分中最小的若干个数。 因此将 N 个数从小到大排序后,最优解一定是一个前缀。 枚举每个前缀,二分出严格大于平均数的数字个数。
#include<bits/stdc++.h>
using namespace std ;
typedef long long ll ;
const int maxn = 1e6 + 10 ;
const int inf = 0x3f3f3f3f ;
int a[maxn] ;
double sum[maxn] ;
void deal(){
int n ; scanf("%d" , &n) ;
for(int i = 1 ; i <= n ; i++){
scanf("%d" , &a[i]) ;
}
sort(a+1 , a+1+n) ;
for(int i = 1 ; i <= n ; i++){
sum[i] = a[i] + sum[i-1] ;
}
int ans = 0 ;
for(int i = 1 ; i <= n ; i++){
double avg = sum[i] / i ;
int l = 1 , r = i ;
while(l < r){
int mid = l+r >> 1 ;
if(a[mid] > avg)r = mid ;
else l = mid+1 ;
}
ans = max(ans , i-l+1) ;
}
cout << ans << endl ;
}
int main(){
deal() ;
return 0 ;
}
G. Easy Glide
思路:用结构体存储每一个点,开始点是0点,结束点是n+1点,然后计算i点到j点所花的时间,再用dijkstra算法计算最短时间
注意点:出发点不能加速;数据要开long long。
#include<bits/stdc++.h>
using namespace std ;
typedef long long ll ;
const int maxn = 1e3 + 10 ;
const int inf = 0x3f3f3f3f ;
struct node{
ll x , y ;
}p[maxn];
double g[maxn][maxn] , d[maxn] ;
int vis[maxn] ;
void deal(){
int n ; cin >> n ;
fill(d , d+maxn , inf) ;
for(int i = 1 ; i <= n ; i++){
ll u , v ; scanf("%lld %lld" , &u , &v) ;
p[i].x = u , p[i].y = v ;
}
scanf("%lld %lld %lld %lld" , &p[0].x , &p[0].y , &p[n+1].x , &p[n+1].y) ;
ll v1 , v2 ;
scanf("%lld %lld" , &v1 , &v2) ;
for(int i = 0 ; i <= n+1 ; i++){
for(int j = 0 ; j <= n+1 ; j++){
if(i == j){
g[i][j] = 0 ;
continue ;
}
double dis = sqrt(abs((p[i].x - p[j].x) * (p[i].x - p[j].x)) + abs((p[i].y - p[j].y) * (p[i].y - p[j].y))) ;
if(v2*3 >= dis && i != 0){
g[i][j] = dis/v2 ;
}else if(v2*3 < dis && i != 0){
g[i][j] = 3+(dis-v2*3)/v1 ;
}else{
g[i][j] = dis/v1 ;
}
}
}
d[0] = 0 ;
for(int i = 0 ; i <= n+1 ; i++){
int t = -1 , mind = 0 ;
for(int j = 0 ; j <= n+1 ; j++){
if(!vis[j]){
if(t == -1 || mind > d[j]){
t = j ;
mind = d[j] ;
}
}
}
if(t == -1)break ;
vis[t] = 1 ;
for(int j = 0 ; j <= n+1 ; j++){
if(!vis[j]){
d[j] = min(d[j] , d[t]+g[t][j]) ;
}
}
}
printf("%.6lf\n" , d[n+1]) ;
}
int main(){
deal() ;
return 0 ;
}
M. BpbBppbpBB
假设黑色格子数为cnt1 , 白色格子组成的洞数为cnt2 , 而C印章数为a , S印章数为b
C印章的黑色格子数为146,S印章的黑色格子数为100
C印章的白洞为2,S印章的白洞为1
则a*146 + b*100 = cnt1 , a*2+b = cnt2
所以只要求出cnt1,cnt2,然后解方程就好了
如何判断是否是白洞呢?
我是先用bfs计算出一个白色连通块中白色格子的个数 == 12,且该白色连通块的形状是4*4的(可以自己比划一下,用俩个印章拼接是组不出4*4的白色连通块且其中白色格子的个数 == 12的)
#include<bits/stdc++.h>
using namespace std ;
typedef long long ll ;
const int maxn = 1e3 + 10 ;
const int inf = 0x3f3f3f3f ;
char c[maxn][maxn] ;
int vis[maxn][maxn] ;
int X[4] = {1 , 0 , -1 , 0} ;
int Y[4] = {0 , 1 , 0 , -1} ;
int n , m ;
struct node {
int x , y ;
};
bool bfs(int x , int y){
queue<node > q ;
node temp ;
temp.x = x , temp.y = y ;
q.push(temp) ;
vis[x][y] = 1 ;
int cnt = 0 ;
int maxx = x , maxy = y , minx = x , miny = y ;
while(!q.empty()){
node top = q.front() ;
q.pop() ;
cnt++ ;
for(int i = 0 ; i < 4 ; i++){
int nx = top.x + X[i] ;
int ny = top.y + Y[i] ;
if(vis[nx][ny] == 0 && c[nx][ny] == '.'){
if(nx >= 0 && nx < n && ny >= 0 && ny < m){
vis[nx][ny] = 1 ;
temp.x = nx , temp.y = ny ;
q.push(temp) ;
maxx = max(maxx , nx) ;
maxy = max(maxy , ny) ;
minx = min(minx , nx) ;
miny = min(miny , ny) ;
}
}
}
}
if(cnt == 12 && maxx - minx == 3 && maxy - miny == 3)return true ;
else return false ;
}
void deal(){//C:146 S:100
cin >> n >> m ;
int cnt1 = 0 , cnt2 = 0 ;
for(int i = 0 ; i < n ; i++){
scanf("%s" , c[i]) ;
for(int j = 0 ; j < m ; j++){
if(c[i][j] == '#'){
cnt1++ ;
}
}
}
for(int i = 0 ; i < n ; i++){
for(int j = 0 ; j < m ; j++){
if(c[i][j] == '.'){
if(bfs(i , j))cnt2++ ;
}
}
}
for(int i = 0 ; i <= cnt1/146 ; i++){
if((cnt1 - 146*i) % 100 == 0){
for(int j = 0 ; j <= (cnt1 - 146*i)/100 ; j++){
if(i*2 + j == cnt2){
cout << i << " " << j << endl ;
return ;
}
}
}
}
}
int main(){
deal() ;
return 0 ;
}
I. Barbecue
思路:若一开始就是回文串,那就后手赢;若一开始不是回文串,如果这子串不管是掐头还是去尾都是回文串的话,这个子串的情况类似于,ab,abab,ababab,这说明终止态的子串长度一定是偶数,因此输赢只和起始串长度 的奇偶性有关。
但又因为n = 1e6 , q = 1e6 ,使用一般方法判断是否是回文的时间复杂度是O(n*q),这必然会超时,用字符串哈希判断是否是回文的时间复杂度是O(1),所以我们要用字符串哈希来降低判断是否是回文的时间复杂度。
#include<bits/stdc++.h>
using namespace std ;
typedef long long ll ;
typedef unsigned long long ULL ;
const int maxn = 1e6 + 10 ;
const int inf = 0x3f3f3f3f ;
const int base = 131 ;
char s[maxn] ;
//h是字符串正序hash值,h1是字符串逆序hash值
ULL p[maxn] , h[maxn] , h1[maxn] ;
int n , m ;
ULL get(int l , int r){
return h[r] - h[l-1] * p[r-l+1] ;
}
ULL get1(int l , int r){//求逆序哈希值
//因为是从n开始的第l-1个,和第r个
return h1[n-l+1] - h1[n-r] * p[r-l+1] ;
}
void deal(){
scanf("%d %d %s" , &n , &m , s+1) ;
p[0] = 1 ;
for(int i = 1 ; i <= n ; i++){
h[i] = h[i-1] * base + s[i] - 'a' + 1 ;
h1[i] = h1[i-1] * base + s[n-i+1] - 'a' + 1 ;
p[i] = p[i-1] * base ;
}
for(int i = 0 ; i < m ; i++){
int l , r ; scanf("%d %d" , &l , &r) ;
if(get(l , r) == get1(l , r) || ((r-l) & 1)){
printf("Budada\n") ;
}else{
printf("Putata\n") ;
}
}
}
int main(){
deal() ;
return 0 ;
}