A - 冬 知识点: 思维 题意:找到另一个整点 C,使顶点组成的三角形任意两边之和大于第三边,且所组成的三角形面积是正整数。 分析:要使面积是整数那就让底乘高为偶数。可以去构造一个与坐标轴平行的边且长度为偶数作为底边 代码实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 #include <bits/stdc++.h> using namespace std;#define int long long #define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0); const int N=2e5 +5 ;const int mod=998244353 ;void solve () { int x1,y1,x2,y2; cin>>x1>>y1>>x2>>y2; if (x1==x2){ cout<<x1+2 <<" " <<y1<<endl; }else { cout<<x1<<" " <<y1+2 ; } } signed main () { IOS int t=1 ; while (t--) { solve (); } }
B - 至 知识点: 贪心 题意:给一个偶数,要拆解成尽可能多的偶数。 分析:遇到偶数就切割,遇到奇数就和它右边遇到的第一个偶数结合。麻烦的是进行排序。 代码实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 #include <bits/stdc++.h> using namespace std;#define int long long #define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0); string s; vector<string> v; bool cmp (string &a,string &b) { if (a.size ()==b.size ()) return a<b; else return a.size ()<b.size (); } void solve () { cin>>s; for (int i=0 ,j=0 ;i<s.size ();i++) { if ((s[i]-'0' )%2 ==0 ) { v.push_back (s.substr (j,i-j+1 )); j=i+1 ; } } sort (v.begin (),v.end (),cmp); for (auto c:v) { cout<<c<<endl; } } signed main () { IOS int t=1 ; while (t--) { solve (); } }
C - 记 知识点: 构造 题意: 分析:相邻两集合有且只有一个值重复,对于示例,更容易发现规律的结果应该是
也就是说构造这样的对称矩阵就能满足题意 代码实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 #include <bits/stdc++.h> using namespace std;#define int long long #define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0); const int N=505 ;int a[N][N];void solve () { int n; cin>>n; int cnt=1 ; for (int i=1 ;i<=n;i++) { for (int j=i;j<=n;j++)a[i][j]=cnt++; for (int j=1 ;j<=i;j++)a[i][j]=a[j][i]; } for (int i=1 ;i<=n;i++) { for (int j=1 ;j<=n;j++)cout<<a[i][j]<<" " ; cout<<endl; } } signed main () { IOS int t=1 ; while (t--) { solve (); } }
D - 得 知识点: 贪心 题意:所有拉雪橇的驯鹿的力量总和必须大于或等于所有坐在雪橇上的驯鹿的体重总和,最多有多少只驯鹿能坐在雪橇上。 分析: 很简单的一个要求就是让拉雪橇的鹿的力量大于等于坐雪橇的鹿的体重。 是所有鹿的力量和。 是坐雪橇驯鹿的力量和 两者相减就是拉雪橇的总力量。 是坐雪橇驯鹿的体重和; 要求 即 贪心一点,我们在选择时选择代价小的(排个序从第一个开始选)。 代码实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 #include <bits/stdc++.h> using namespace std;#define int long long #define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0); const int N=3e5 +5 ;void solve () { int n; cin>>n; vector<int > a; int power=0 ; for (int i=1 ;i<=n;i++) { int w,p; cin>>w>>p; power+=p; a.push_back (w+p); } sort (a.begin (),a.end ()); int sum=0 ,cnt=0 ; for (int i=0 ;i<n;i++) { if ((sum+a[i])<=power) { cnt++; sum+=a[i]; }else break ; } cout<<cnt<<endl; } signed main () { IOS int t; cin>>t; while (t--) { solve (); } }
E - 吃 知识点: 思维 题意:给出一个排列的前缀最小值数组,求有多少个排列满足要求。 分析: 长度为 n 的排列是从 1~n 这个 n 个整数按任意顺序组成的数组。 我们先来模拟一下,假如这个数组为{1,2,3}
1 2 3 min{p[1 ]}=1 ; min{p[1 ],p[2 ]}=2 ; min{p[1 ],p[2 ],p[3 ]}=3 ;
可以发现上面是绝对错误的,所以对于这个前缀最小值数组是非递增的(因为后面的前缀必然包含当下前缀的最小值,超过的话这个数组就是错误的)。此时排列数量为 0。 如何计算这个变化,对于一个完全不同的数组{3,2,1}。我们可以推出结果只有一种那就是{3,2,1}。排列的数量的更新其实是取决于前缀数组中相同的数。 比如:{2,2,1} 此时的排列可以是{2,2,1}也可以是{2,3,1}。 所以当前前缀最小值等于之前的前缀最小值时可以选择的放置数量为 。(PS: 注意因为是排列所以不能有重复数字,需要减去之前用过的 i 个数) 代码实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 #include <bits/stdc++.h> using namespace std;#define int long long #define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0); const int N=2e5 +5 ;const int mod=998244353 ;void solve () { int n; cin>>n; int a[N]; for (int i=0 ;i<n;i++) cin>>a[i]; int ma=a[0 ]; int ans=1 ; for (int i=1 ;i<n;i++) { if (a[i]==ma)ans=ans*(n-ma-i+1 )%mod; else if (a[i]>ma){ cout<<"0" <<endl; return ; }else ma=a[i]; } cout<<ans%mod<<endl; } signed main () { IOS int t; cin>>t; while (t--) { solve (); } }
F - 饺 知识点: 01 BFS (双端队列) 来源于 BFS(图论) - OI Wiki 的惯用伪代码
1 2 3 4 5 6 7 8 9 10 11 while (队列不为空) { int u = 队首; 弹出队首; for (枚举 u 的邻居) { 更新数据 if (...) 添加到队首; else 添加到队尾; } }
题意:有一个 N × M 的矩阵 a,a 中的元素可能是 / 或 \ ,左上角是电源,右下角是灯。要得到亮灯的最少操作次数。 分析: 我们要搜索从开关到灯的最短路径。我们把交叉点视为格点,每个格点会有四个对角格点, 出界的不能选择,无法达到更优结果的也能不选。此时就有两种状态:连通路径和不连通路径,为了使操作次数最少,优先选连通的。具有两端性 (0 和 1) 对于更优的从双端队列队头入队,不优的从队尾入队。 每个状态可能入队多次,但是只使用一次。 代码实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 #include <bits/stdc++.h> using namespace std;#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0); #define PII pair<int,int> #define x first #define y second int dx[]={-1 ,-1 ,1 ,1 };int dy[]={-1 ,1 ,1 ,-1 }; int ex[]={-1 ,-1 ,0 ,0 };int ey[]={-1 ,0 ,0 ,-1 };char s[5 ] = "\\/\\/" ;const int N=505 ;char mp[N][N];int dis[N][N];bool vis[N][N];int bfs (int n,int m) { memset (dis,0x3f ,sizeof dis); dis[0 ][0 ]=0 ; deque<PII> q; q.push_back ({0 ,0 }); while (q.size ()) { PII u=q.front (); q.pop_front (); int xx=u.x,yy=u.y; if (vis[xx][yy])continue ; vis[xx][yy]=true ; for (int i=0 ;i<4 ;i++) { int a=xx+dx[i],b=yy+dy[i]; if (a<0 ||a>n||b<0 ||b>m)continue ; int ea=xx+ex[i],eb=yy+ey[i]; int d=dis[xx][yy]+(mp[ea][eb]!=s[i]); if (d<dis[a][b]) { dis[a][b]=d; if (mp[ea][eb]!=s[i]) q.push_back ({a,b}); else q.push_front ({a,b}); } } } return dis[n][m]; } void solve () { int n,m; cin>>n>>m; for (int i=0 ;i<n;i++) { for (int j=0 ;j<m;j++)cin>>mp[i][j]; } int d=bfs (n,m); if (d==0x3f3f3f3f )cout<<"NO SOLUTION" ; else cout<<d; } signed main () { IOS int t=1 ; while (t--) { solve (); } }
G - 子 知识点: 枚举 题意:从数组里面选一些数字使得被选中的数字构成一个等比数列,要求选的数字个数最多 分析: 可以枚举每个数,把它当作等比数列首项,再从 2 开始枚举公比。为避免超时要进行优化,如果当前需求的值超过数组最大值直接结束或者当前最多相同数字个数已经超出该数所能实现的时也 break。 代码实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 #include <bits/stdc++.h> using namespace std;#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0); #define int long long const int N=2e5 +5 ;int a[N],b[N];void solve () { int n; cin>>n; int ans=1 ; for (int i=0 ;i<n;i++) { cin>>a[i]; b[a[i]]++; ans=max (ans,b[a[i]]); } sort (a,a+n); for (int i=2 ;i<=a[n-1 ];i++) { for (int j=0 ;j<n;j++) { if (pow (i,ans)*a[j]>a[n-1 ])break ; int res=a[j],cnt=1 ; while (res*i<=a[n-1 ]&&b[res*i]) { res*=i; cnt++; } ans=max (ans,cnt); } } cout<<ans; } signed main () { IOS int t=1 ; while (t--) { solve (); } }
欢迎关注我的微信公众号呀微信公众号文章链接