TOYOTA SYSTEMS Programming Contest 2022(AtCoder Beginner Contest 279)A-F题(暂定)
FA,w是两个v是一个 送分题
#include<bits/stdc++.h> using namespace std ; #define maxn 400100 #define int long long int read(){ int ans = 0 , f = 1 ; char ch = getchar() ; while ( !isdigit(ch) ){ if( ch == '-' ) f = -1 ; ch = getchar() ; } while ( isdigit(ch) ) ans = (ans * 10) + (ch ^ '0') , ch = getchar() ; return ans * f ; } char in[maxn] ; signed main(){ // freopen("test.in" , "r" , stdin) ; // freopen("test.out" , "w" , stdout) ;\ scanf("%s" , in + 1) ; int len = strlen(in + 1) ; int sum = 0 ; for(int i = 1 ; i <= len ; i++){ if(in[i] == 'v') sum++ ; else sum += 2 ; } printf("%lld" , sum) ; return 0 ; }
B.数据范围很小 直接暴力判断即可
#include<bits/stdc++.h> using namespace std ; #define maxn 400100 #define int long long int read(){ int ans = 0 , f = 1 ; char ch = getchar() ; while ( !isdigit(ch) ){ if( ch == '-' ) f = -1 ; ch = getchar() ; } while ( isdigit(ch) ) ans = (ans * 10) + (ch ^ '0') , ch = getchar() ; return ans * f ; } char s[maxn] , t[maxn] ; int slen , tlen ; bool check(int st){ if(st + tlen - 1 > slen) return 0 ; for(int i = 1 ; i <= tlen ; i++) if(s[st + i - 1] != t[i]) return 0 ; return 1 ; } signed main(){ // freopen("test.in" , "r" , stdin) ; // freopen("test.out" , "w" , stdout) ; scanf("%s" , s + 1) ; scanf("%s" , t + 1) ; slen = strlen(s + 1) ; tlen = strlen(t + 1) ; if(tlen > slen){ printf("No") ; return 0 ; } for(int i = 1 ; i <= slen ; i++){ if(check(i)){ printf("Yes") ; return 0 ; } } printf("No") ; return 0 ; }
C.判断前面的每一竖列是否能在后面找到一样的 对于每一个竖列 计算哈希值以及有多少个 然后和后面进行比较即可
#include<bits/stdc++.h> using namespace std ; #define maxn 400100 #define int long long int read(){ int ans = 0 , f = 1 ; char ch = getchar() ; while ( !isdigit(ch) ){ if( ch == '-' ) f = -1 ; ch = getchar() ; } while ( isdigit(ch) ) ans = (ans * 10) + (ch ^ '0') , ch = getchar() ; return ans * f ; } int hsh[maxn] ; const int mod = 998244353 ; int bse = 12281 ; char in[maxn] ; int num[maxn] ; int h , w ; int pos(int i , int j){ return (i - 1) * w + j ; } map<int,int> mp1 ; map<int,int> mp2 ; int vt[maxn] , cnt ; signed main(){ // freopen("test.in" , "r" , stdin) ; // freopen("test.out" , "w" , stdout) ; h = read() , w = read() ; for(int i = 1 ; i <= h ; i++){ scanf("%s" , in + 1) ; for(int j = 1 ; j <= w ; j++) if(in[j] == '#') num[pos(i , j)] = 3 ; else num[pos(i , j)] = 7 ; } for(int i = 1 ; i <= w ; i++){ int sum = 0 ; for(int j = 1 ; j <= h ; j++) sum = (sum * bse + num[pos(j , i)]) % mod ; // printf("sum : %lld \n") if(!mp1[sum]) mp1[sum] = 1 , vt[++cnt] = sum; else mp1[sum]++ ; } // printf("cnt : %lld \n" , cnt) ; for(int i = 1 ; i <= h ; i++){ scanf("%s" , in + 1) ; for(int j = 1 ; j <= w ; j++) if(in[j] == '#') num[pos(i , j)] = 3 ; else num[pos(i , j)] = 7 ; } for(int i = 1 ; i <= w ; i++){ int sum = 0 ; for(int j = 1 ; j <= h ; j++) sum = (sum * bse + num[pos(j , i)]) % mod ; if(!mp2[sum]) mp2[sum] = 1; else mp2[sum]++ ; } for(int i = 1 ; i <= cnt ; i++) if(mp1[vt[i]] != mp2[vt[i]]){ printf("No") ; return 0 ; } printf("Yes") ; return 0 ; }
D.求导之后进行二分找到最后一个使导函数大于0的点和第一个使导函数小于0的点 然后比较一下两边的值
#include<bits/stdc++.h> using namespace std ; #define maxn 400100 #define int long long int read(){ int ans = 0 , f = 1 ; char ch = getchar() ; while ( !isdigit(ch) ){ if( ch == '-' ) f = -1 ; ch = getchar() ; } while ( isdigit(ch) ) ans = (ans * 10) + (ch ^ '0') , ch = getchar() ; return ans * f ; } double A , B ; signed main(){ // freopen("test.in" , "r" , stdin) ; // freopen("test.out" , "w" , stdout) ; cin >> A >> B ; double C = A / (2.0 * B) ; int l = 0 , r = pow(10 , 18) ; int mid = (l + r) / 2 , ans = 0 ; while(l <= r){ if(pow(1 + mid , 1.5) <= C) ans = mid , l = mid + 1 ; else r = mid - 1 ; mid = (l + r) / 2 ; // printf("l : %lld r: %lld \n" , l , r ) ; } double ansa , ansb ; ansa = B * ans + A / pow(1 + ans , 0.5) ; ans++ ; ansb = B * ans + A / pow(1 + ans , 0.5); printf("%.10lf" , min(ansa , ansb)) ; return 0 ; }
E
首先我觉得最简单方法应该就是安哥的方法 但是我看到了一种分治的思想 我觉得也有道理 分享一下
具体来说 对于我们要计算的一个区间[l,r] 我们需要依次考虑每一个操作缺失的情况对吧
那么当我们在考虑[l,mid]时 右边所有的操作一定已经完成了 所以我们可以把右边的操作完成掉 然后再去计算[l,mid] 这一段
在计算完左边的答案之后 左边的操作一定都可以完成了 然后我们再计算右边的答案
但问题在于就这个题目来说 答案的合并我不知道如何完成 如果有能写出来的同学请帮帮我 希望得到大神指点 !
F
首先一眼并查集 很容易想到 但是唯一的难点就是插入这个地方
如果它插入的盒子里的球没有了 那么就比较麻烦了
所以我们每次把y并入到x中的时候 完全可以新建一个盒子 那么以后有y的话 就可以直接塞到新盒子里了 最后我们统计新盒子的实际上是谁(ans数组)以及每一个盒子现在的编号(id)就可以
注意一下实现的细节 在代码里标注了
#include<bits/stdc++.h> using namespace std ; #define maxn 900100 #define int long long int read(){ int ans = 0 , f = 1 ; char ch = getchar() ; while ( !isdigit(ch) ){ if( ch == '-' ) f = -1 ; ch = getchar() ; } while ( isdigit(ch) ) ans = (ans * 10) + (ch ^ '0') , ch = getchar() ; return ans * f ; } int fa[maxn] , id[maxn] , ans[maxn] ; // id[i] 表示现在i号盒子对应的真正的编号 // ans[i] 表示真正的编号对于的题目中的i号盒子 //二者互相映射 int find(int x){ if(fa[x] == x) return fa[x] ; return fa[x] = find(fa[x]) ; } int n , q ; void merge(int x , int y){ int fx = find(x) , fy = find(y) ; if(fx != fy) fa[fy] = fx ; return ; } int totball , totbox ; signed main(){ // freopen("test.in" , "r" , stdin) ; // freopen("test.out" , "w" , stdout) ; n = read() , q = read() ; totball = n ; totbox = n + q ; // 这里新盒子的编号一定要从n+q开始 要不然可能会和小球的编号撞了 在并查集路径压缩的时候会出现混乱 for(int i = 1 ; i <= n + 2 * q ; i++) fa[i] = ans[i] = id[i] = i ; while(q--){ int op = read() , x = read() ; if(op == 1){ int y = read() ; merge(id[x] , id[y]) ; totbox++ ; id[y] = totbox ; ans[totbox] = y ; fa[totbox] = totbox ; // printf("fa[%lld] : %lld find : %lld \n" , totbox , fa[totbox] , find(totbox)) ; } else if(op == 2){ totball++ ; fa[totball] = find(id[x]) ; // printf("id[%lld] : %lld fa : %lld \n" , x , id[x] , find(id[x])) ; } else { printf("%lld\n" , ans[find(x)]) ; } } return 0 ; }

浙公网安备 33010602011771号