A(签到)
数据范围小 预处理一下所有合法的数查询即可
B(GCD)
题意:判断数组中是否存在两个数字的gcd大于1
暴力:由于随机数据 并且只需要找到一组 所以数据不会故意放在遍历的最后一次 直接两层循环暴力即可解决
第二种思路是 对每个数组 分解质因数 然后用map维护每个质因数上次出现的位置 如果一个质因数出现了两次 那么输出这两个位置即可
第二种思路代码:
cpp
#include<bits/stdc++.h>
using namespace std;
vector<int>f(int x){
vector<int>v;
for(int i=2;i*i<=x;i++){
if(x%i==0){
v.push_back(i);
while(x%i==0)x/=i;
}
}
if(x>1)v.push_back(x);
return v;
}
void solve(){
int n;cin>>n;
vector<int>a(n);
for(int i=0;i<n;i++)cin>>a[i];
map<int,int>mp;
for(int i=0;i<n;i++){
int x=a[i];
vector<int>fs=f(x);
for(int p:fs){
if(mp.count(p)){
cout<<mp[p]<<" "<<x<<"\n";
return;
}
}
for(int p:fs)mp[p]=x;
}
cout<<"-1\n";
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
int T;cin>>T;
while(T--)solve();
return 0;
}
C(构造、前缀和、Kadane(最大子段和))
大致题意: 01串每次可以选择一个交替串01反转 目标是将所有串都变为交替串
我们的目标串只有0101010 和1010101 两种 我们可以分别以两个目标串为目标都做一遍 然后取最小值 对于一种目标串 我们将错误的部分提取出来 成为一个字串 我们用c1 c0维护当前以1 或 0 结尾的子序列有几个 遍历一遍需要改变的部分 如果为0 那么结尾为1 的串-1 结尾为0的串+1 若没有则新开一个串 0 结尾 以此类推
cpp
#include <bits/stdc++.h>
using namespace std;
int check(string s){
int c1=0,c0=0;
for(auto x:s){
if(x=='1'){
if(c0==0)c1++;
else c1++,c0--;
}else if(x=='0'){
if(c1==0)c0++;
else c1--,c0++;
}
}
return c0+c1;
}
void solve(){
int n;cin>>n;
string s;
cin>>s;
string s1,s2;
for(int i=0;s[i];i++){
if((i%2==1&&s[i]=='0')||(i%2==0&&s[i]=='1'))s1.push_back(s[i]);
if((i%2==1&&s[i]=='1')||(i%2==0&&s[i]=='0'))s2.push_back(s[i]);
}
cout<<min(check(s1),check(s2))<<'\n';
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int t;cin>>t;
while(t--)solve();
return 0;
}
F(博弈、最短路、构造)
要到达n列 那么要往右n-1次 剩下的就是不得不向另一方向走的路径
观察可得 每五列都会有一次强制换行 所以答案为n-1+n/5
cpp
#include<bits/stdc++.h>
using namespace std;
#define int long long
void solve(){
int n;
cin>>n;
cout<<n-1+n/5<<"\n";
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);
int _;
cin>>_;
while(_--)solve();
return 0;
}
G(排序)
要改变砝码状态 我们肯定要优先选择大的砝码拿走 可以排序后直接遍历一遍即可 直到状态改变 或者不排序 直接存到大根堆里面 每次拿出堆顶
代码如下:
cpp
#include <bits/stdc++.h>
using namespace std;
const int N=1e5+5;
#define int long long
int a[N],b[N];
int n,m;
void solve(){
cin>>n>>m;
priority_queue<int>aq,bq;
int ans=0;
long long suma=0,sumb=0;
for(int i=1;i<=n;i++)cin>>a[i],aq.push(a[i]),suma+=a[i];
for(int i=1;i<=m;i++)cin>>b[i],bq.push(b[i]),sumb+=b[i];
if(suma==sumb)ans=1;
else if(suma>sumb){
while(suma>sumb){
int u=aq.top();aq.pop();
suma-=u;
ans++;
}
}else if(sumb>suma){
while(sumb>suma){
int u=bq.top();bq.pop();
sumb-=u;
ans++;
}
}
cout<<ans<<'\n';
}
signed main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int t;cin>>t;
while(t--)solve();
return 0;
}
H(计算几何)
向量叉乘 推一下面积公式 然后直接做即可
此处给py代码 cpp要注意精度
python
xa,ya=input().split()
xb,yb=input().split()
xa=float(xa)
ya=float(ya)
xb=float(xb)
yb=float(yb)
dy=ya-yb
if abs(dy)<0.000000001:
area=0.5*abs(ya*(xa-xb))
if abs(area-2)<0.000001:
print("0")
else:
print("no answer")
else:
D=xa*yb-ya*xb
x=(-D+4)/dy
print(x)
J(二叉树/二进制)
求完全二叉树某一层的节点个数
对于全满的某一层 若深度为d 那么就有2^(d-1)个 所以判断一下深度即可 如果询问的层数不是最后一层 那就满 否则减去前几层就行了
cpp
#include <bits/stdc++.h>
using namespace std;
#define int long long
int depth(int x) {
int d = 0;
while ((1LL << (d + 1)) <= x) {
d++;
}
return d;
}
void solve() {
int n, q;
cin >> n >> q;
while (q--) {
int x;
cin >> x;
int d = depth(x);
int start = (1LL << d);
int end = min(n, (1LL << (d + 1)) - 1);
cout << (end - start + 1) << '\n';
}
}
signed main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int t;
cin >> t;
while (t--) {
solve();
}
return 0;
}