2.1比赛(CF二合一)
A题
题意:两个人,假设A叫做纪少,B 叫做赵XX;
然后纪少会藏一个灯笼之后,赵XX 再拿一个纪少的灯笼,与自己的灯笼配对,
问题是,这个配对的灯笼总亮度,纪少想尽可能的小,赵XX 与之相反
思路:暴力,因为数据范围很小,n^2不会超时,所以先找到配对最大的那个灯笼,标记下标,找到除此之外最大 的配对亮度
#include <cstdio> #include <iostream> #include <algorithm> #include <cmath> #include <string> #include <vector> #include <set> #include <queue> #include <cstring> #include <cassert> #define ll long long using namespace std; void clear(unsigned char *pta, int size ) { while(size>0) { *pta++ = 0; size --; } } struct node { unsigned long long x, y, z; ll step ; }; node p[100000]; ll cmp(ll a, ll b){ return a>b; } int main() { vector<ll> ar,arr,br,brr; int n, m ;cin >>n>>m; for(int i=0;i<n;i++){ ll kk;cin >>kk; //if(kk<0) arr.push_back(kk); ar.push_back(kk); } ll ma=-9e18+1; for(int i=0;i<m;i++){ ll kk;cin >>kk; // if(kk<0) brr.push_back(kk); br.push_back(kk); }ll x , y ; for(int i=0;i<n;i++){ for(int j=0;j<m;j++){ if(ar[i]*br[j]>ma){ ma = ar[i]*br[j]; x = i; y = j; } } }ma=-9e18+1; for(int i=0;i<n;i++){ for(int j=0;j<m;j++){ if(i== x)continue; if(ar[i]*br[j]>ma){ ma = ar[i]*br[j]; } } }cout<<ma<<endl;}
B题
题意:给一个数,问你是否可以用图形封闭的数量表示出来,能就表示出来,不能就-1(0-9图形封闭的数是0,4,6,8,9,除了8是2个封闭图形,都是1)
思路:首先看范围,发现是1e18,也就是说极端情况都是8的情况下,也就是32,也就说n>32 的都表示不了,然后剩下的2的倍数就全输出8,奇数就先输出0(4,6,9),在全输出8;
#include <cstdio> #include <iostream> #include <algorithm> #include <cmath> #include <string> #include <vector> #include <set> #include <queue> #include <cstring> #include <cassert> #define ll long long using namespace std; void clear(unsigned char *pta, int size ) { while(size>0) { *pta++ = 0; size --; } } struct node { unsigned long long x, y, z; ll step ; }; node p[100000]; ll cmp(ll a, ll b){ return a>b; } int main() { ll n;cin >>n; if(n>36)cout<<"-1"; else { if(n%2){ cout<<4; for(int i=0;i<(n-1)/2;i++)cout<<"8"; } else if(n%2==0) for(int i=0;i<n/2;i++)cout<<"8"; } cout<<endl; }
C题
题意:问你在区间翻转的条件下,找到最长上升子序列的长度
思路:板子题,看懂题,上网找一个板子就过了
#include<bits/stdc++.h> using namespace std; typedef long long ll; int maxn = 2200; int maxm = 2200; int n, a[20000], dp[2001][2001], b[20000]; int ans, ansl, ansr, l, r, cnt; int al[2001][2001], ar[2001][2001]; int solve() { for(int i = 0; i <= cnt; i++) dp[0][i] = 0; for(int i = 1; i <= n; i++) { for(int j = 1; j <= cnt; j++) { dp[i][j] = dp[i - 1][j]; al[i][j] = al[i - 1][j];//al记录翻转的左端点 ar[i][j] = ar[i - 1][j];//al记录翻转的左端点 if(a[i] == b[j]) { dp[i][j] = dp[i - 1][j] + 1; if(l == j && !al[i][j])//如果当前的j就是b开始翻转的左端点,更新记录 al[i][j] = i; if(r == j)//当前的j是b翻转的右端点,记录更新 ar[i][j] = i; } if(dp[i][j - 1] > dp[i][j])//如果答案有更新就要更新答案 { dp[i][j] = dp[i][j - 1]; al[i][j] = al[i][j - 1]; ar[i][j] = ar[i][j - 1]; } } } return dp[n][cnt]; } int main() { //int t; //scanf("%d", &t); cin >>n; for(int i=1;i<=n;i++)cin >>a[i]; cnt = 0; for(int i = 0; i <= 9; i++) b[++cnt] = i; ansl = ansr = l = r = 1; ans = solve(); for(int i = 0; i <= 9; i++) //枚举翻转b数组的每一段 { for(int j = i + 1; j <= 9; j++) { cnt = 0; for(int k = 0; k <= i; k++) b[++cnt] = k; l = cnt+1;//左端点 for(int k = j; k >= i; k--)//只翻转i~j区间的数 b[++cnt] = k; r = cnt;//右端点 for(int k = j; k <= 9; k++) b[++cnt] = k; /* for(int i=1; i<=cnt; i++) printf("%d ",b[i]); printf("\n");*/ int tmp = solve(); if(ans < tmp)//不断更新答案 && al[n][cnt] && ar[n][cnt] { ans = tmp; } } } printf("%d\n", ans); return 0; }
E题
题意就是循环三次后,能否回去
思路:暴力,用数组存后,三重嵌套查询;
#include <cstdio> #include <iostream> #include <algorithm> #include <cmath> #include <string> #include <vector> #include <set> #include <queue> #include <cstring> #include <cassert> #define ll long long using namespace std; void clear(unsigned char *pta, int size ) { while(size>0) { *pta++ = 0; size --; } } struct node { unsigned long long x, y, z; ll step ; }; node p[100000]; ll cmp(ll a, ll b){ return a>b; } int ar[1000000]; ll br[1000000]; int main() { int n;cin >>n; for(int i=1;i<=n;i++) { cin >>ar[i]; } for(int i=1;i<=n;i++){ if(ar[ar[ar[i]]]==i){ return cout<<"YES"<<endl,0; } }cout<<"NO"<<endl; }
F题
题意:n 个仓鼠,k种笼子型号。问你最多能装多少仓鼠,并输出笼子型号
思路:暴力,遍历一遍找能存最多仓鼠的笼子即可
#include <cstdio> #include <iostream> #include <algorithm> #include <cmath> #include <string> #include <vector> #include <set> #include <queue> #include <cstring> #include <cassert> #define ll long long using namespace std; void clear(unsigned char *pta, int size ) { while(size>0) { *pta++ = 0; size --; } } struct node { unsigned long long x, y, z; ll step ; }; node p[100000]; ll cmp(ll a, ll b){ return a>b; } int ar[1000000]; ll br[1000000]; ll mi =0x7f7f7f ; int main() { ll n ;int k; cin >>n;cin >>k; long long ma=1e18+1 , cnt =0 ,pos=0; for(int i=1;i<=k;i++){ long long num; cin >>num; if(ma>n%num){ ma = n%num; pos = i; cnt = n/num; } } cout<<pos<<" "<<cnt<<endl; }
G题
题意:一堆时区的人想打比赛,每个临近的时区只差一个小时,问在第一时区第几小时的时候,参赛人数最多。
思路:可以说是尺取法,或者叫做暴力,位移时区,具体看代码就懂了
#include <bits/stdc++.h> using namespace std; typedef long long ll; typedef unsigned long long ull; map<pair<int, int>, int> mp; int arr[10000000]; int main() { int n;cin >>n; for(int i=1;i<= n;i++){ cin>>arr[i%n];//使时区变为一个循环 } int s ,f ;cin >>s>>f;int sum =0; int pos =0 ; for(int i =s ;i<f;i++) sum +=arr[i%n];int len = sum ; for(int i=1;i<n;i++){ int l = (s- i + n)%n; int r = (f- i + n)%n; sum +=arr[l]; sum -=arr[r]; if(sum >len){ len = sum ; pos = i; } } cout<<pos +1 <<endl; return 0; }
H题
题意:秀恩爱,给你两个字符串,问你用最小代价下,是这两个字符串相等(相等就是让两个字符可以互相转换)
思路:并查集模板题,然后用两个数组存一下转换的字符就行了
#include <bits/stdc++.h> using namespace std; typedef long long ll; typedef unsigned long long ull; map<pair<int, int>, int> mp; const int maxn = 1e6; int arr[10000000]; int l[1000000]={0}, r[maxn]; int find(int x ){ if(arr[x]!=x)arr[x] = find(arr[x]); return arr[x]; } void bin(int a , int b){ int x ,y; x = find(a); y = find(b); if(x!=y){ arr[x]=y; } } int main() { int n;cin >>n; string s1 ,s2 ;cin >>s1>>s2; int len =0; for(int i=0;i<n;i++){ arr[s1[i]-'a'+1] = s1[i]-'a'+1; arr[s2[i]-'a'+1] = s2[i]-'a'+1; }for(int i=0;i<n;i++){ if(arr[find(s1[i]-'a'+1)]!=arr[find(s2[i]-'a'+1)]){ bin(s1[i]-'a'+1,s2[i]-'a'+1); l[len] = s1[i]-'a'+1; r[len++] = s2[i]-'a'+1; } } cout<<len <<endl; for(int i=0;i<len;i++){ cout<<char(l[i]+'a'-1)<<" "<<char(r[i]+'a'-1)<<endl; } return 0; }