A
#include <iostream>
using namespace std;
int main () {
int n;
cin>>n;
while(n--) {
int a,b;
cin>>a>>b;
if(a < b) {
int c = a;
a = b;
b = c;
}
cout<<a<<b;
}
return 0;
}
B
#include <bits/stdc++.h>
using namespace std;
int main () {
int n;
cin>>n;
while(n--) {
string str;
cin>>str;
bool flag = true;
int n = str.length();
for(int i = 0;i < n;i++) {
for(int j = 0;j < n;j++) {
if(str[i] != str[j]){
flag = false;
swap(str[i],str[j]);
break;
}
}
if(!flag) break;
}
if(flag) {
cout<<"NO"<<endl;
}else{
cout<<"YES"<<endl;
cout<<str<<endl;
}
}
return 0;
}
C
首先通过a和b的值来将钟表的时间分为不包含他们俩的两个区间,然后分别判断c和d是否满足一人一个区间,不能一个区间脚踏两只船吧
#include <bits/stdc++.h>
using namespace std;
int main () {
int n;
cin>>n;
while(n--) {
vector<int> num1;
vector<int> num2;
int a,b,c,d;
cin>>a>>b>>c>>d;
bool flag = false;
if(a > b) swap(a,b);
for(int i = a + 1; i < b; i++) num1.push_back(i);
for(int i = 1; i < a; i++) num2.push_back(i);
for(int i = b + 1; i <= 12; i++) num2.push_back(i);
int n1 = num1.size();
int n2 = num2.size();
for(int i = 0; i < n1; i++) {
if(c == num1[i]) {
flag = true;
break;
}
}
if(flag) {
flag = false;
for(int i = 0; i < n2; i++) {
if(d == num2[i]) {
flag = true;
break;
}
}
} else {
for(int i = 0; i < n1; i++) {
if(d == num1[i]) {
flag = true;
break;
}
}
if(flag) {
flag = false;
for(int i = 0; i < n2; i++) {
if(c == num2[i]) {
flag = true;
break;
}
}
}
}
if(flag) {
cout<<"YES"<<endl;
} else {
cout<<"NO"<<endl;
}
}
return 0;
}
D
首先看一段二进制字符串可以怎么分,如果有连续几个1,就要分一块,那么再看这一块的前后是否含0,如果前面有0就将前面的0一块加上,后面的0不用管,当然这时候就有0又有1 的这一块只能分一个,不然就构不成最小的那个数了。我们的目的就是将所有的1从后向前排然后再排0。
另一种简单的思路:将结果初始化为1,因为如果原字符串不需要变动,这也是一块;然后就是计算01 或 10 这种情况有多少种;最后就是判断是否有这种情况存在,如果存在就将结果 -1 。
#include <iostream>
using namespace std;
int main ()
{
int t;
cin>>t;
while(t--)
{
string str;
cin>>str;
int res = 0;
bool flag = false;
for(int i = str.length()-1;i >= 0;)
{
if(str[i] == '0')
{
res ++;
while(str[i] == '0') i--;
}else if(str[i] == '1')
{
while(str[i] == '1') i--;
if(!flag && i >= 0 && str[i] == '0') {
flag = true;
while(str[i] == '0') i--;
}
res ++;
}
}
cout<<res<<endl;
}
return 0;
}
E
通过二分在a数组中找出第一个大于查找节点的位置,然后就算多出来的这部分时间加上之前的即可
#include <iostream>
#include <cstring>
using namespace std;
const int N = 100010;
int a[N],b[N];
int main ()
{
int t;
scanf("%d",&t);
while(t--)
{
int n,k,q;
scanf("%d%d%d",&n,&k,&q);
for(int i = 1;i <= k;i ++){
scanf("%d",&a[i]);
}
for(int i = 1;i <= k;i ++){
scanf("%d",&b[i]);
}
while(q--) {
int x;
scanf("%d",&x);
int l = 0,r = k;
if(x == 0) {
cout<<"0 ";
continue;
}
while(l < r) {
int mid = (l+r) >> 1;
if(a[mid] <= x) l = mid + 1;
else r = mid;
}
int d = x - a[l-1];
long long sth = (long long)d*(b[l] - b[l-1])/(a[l] - a[l-1]);
cout<<sth + b[l-1]<<" ";
}
cout<<endl;
}
return 0;
}
F
首先只需要计算第一象限中的点数,然后 x 4 + 4 即可。通过遍历纵坐标,然后二分横坐标,遵循大范围-小范围的思想,存在这样的式子:$r^2<=x^2+y^2<(r+1)^2$ 那么二分的时候找到第一个小于$r^2$位置,那么用大范围-小范围即可
#include <iostream>
#include <cstring>
using namespace std;
typedef long long LL;
const int N = 100010;
int a[N],b[N];
double c[N];
int main () {
int t;
scanf("%d",&t);
while(t--) {
int d;
scanf("%d",&d);
int res = 0;
for(int i = 1; i <= d; i++) {
int tl = 0;
int l = 0,r = d;
while(l < r) {
int mid = l + r + 1 >> 1;
if((LL)mid * mid + (LL)i * i < (LL)d * d) l = mid;
else r = mid - 1;
}
tl = l;
l = 0,r = d;
while(l < r) {
int mid = l + r + 1 >> 1;
if((LL)mid * mid + (LL)i * i < (LL)(d + 1) * (d + 1)) l = mid;
else r = mid - 1;
}
res += r - tl;
}
cout<<4+4*res<<endl;
}
return 0;
}
G
使用了一个Map集合,并且要知道一个规律,满足$a_i>>2 == a_j>>2$这个条件的两个值是可以交换的,Map集合的定义:k为$a_i>>2$,v为所有$a_i>>2$相等的值的序列,然后将Map中的每一个序列进行排序,这就会满足字典序最小。最后将Map集合中的所有序列存入到a数组中,并且从后往前存储。
#include <bits/stdc++.h>
using namespace std;
const int N = 100010;
int a[N],b[N];
double c[N];
int main () {
int t;
scanf("%d",&t);
while(t--) {
int n;
scanf("%d",&n);
map<int,vector<int>> m;
vector<int> q(n+1);
for(int i = 1; i <= n; i++) {
scanf("%d",&q[i]);
m[q[i] >> 2].push_back(q[i]);
}
for(auto &t :m) {
sort(t.second.begin(),t.second.end());
}
for(int i = n; i; i--) {
q[i] = m[q[i] >> 2].back();
m[q[i] >> 2].pop_back();
}
for(int i = 1; i <= n; i++) {
printf("%d ",q[i]);
}
puts("");
}
return 0;
}