感觉这场div2比较简单,就是考试的时候B题卡的时间太长了,导致后面的题也没心情看,结束后看才发现很简单,可以轻轻松松的解出来,也没有涉及什么算法知识。
A题的意思是给定只包含Q,A的字符串,询问是否可以匹配所有的回答。需要注意的一个点就是假如A之前没有Q,则这个A没有任何的意义。整体的思路像栈的操作一样。Q进栈,遇到A的话,只要不空栈就出栈,只至为空。
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n,t;
cin >> n;
while (n--)
{
cin >> t;
string s;cin >> s;
int q = 0,a = 0;
int flag = 0;
for (int i = 0;i<t;i++)
{
if (s[i] == 'Q')
{
q++;
}
else if (s[i]== 'A')
{
if (q!=0) q--;
}
}
if (q==0) cout << "Yes"<<"\n";
else cout <<"No"<<"\n";
}
return 0;
}
B题的意思就是自己排列1到n这n个数字,而且取出相邻的两个数字的绝对差值的最小值,并保证这个最小值要最大。刚开始的思路比较乱,在那里乱画,乱举例。其实这类题基本上就是分成几个有顺序的数组,然后进行组合。比如n为12,可以分为两个数组1 2 3 4 5 6和 7 8 9 10 11 12,然后组成一个完整的数组7 1 8 2 9 3 10 4 11 5 12 6,像这样交叉组合,可以保证这个的最大值为6.如果为奇数,可以在最前面加上一个n即可。这个思想感觉有点妙,两两配对,让他们的差值均为n/2.
#include<bits/stdc++.h>
using namespace std;
int a[1006],b[1006];
int main()
{
int n,t;cin >> n;
while (n--)
{
cin >> t;
int mn = t/2;//得出的最小数
for (int i = 1;i<=mn;i++)
{
a[i] = i;
b[i] = i+mn;
}
if (t&1) cout << t<<" ";
for (int i = 1;i<=mn;i++)
{
cout << b[i] <<" " << a[i] <<" ";
}
}
return 0;
}
C1题的意思就是给定一串长度为n的-1,1串,再给定一个规则划分区间,使得区间里面的数字+ -交换操作,得到区间的和,然后所有区间的和是否可以等于0。其实进行简单分析一下就可以得出,假如数字的个数是奇数,那无论怎么配对都不可能成功,直接输出-1,假如个数为偶数,则一定会成功,具体的推理的话,可以分成两两一队,而这一对只有四种可能1 1,1 -1 ,-1 -1 ,-1 1.
这四种可能都可以独立进行划分得到结果0,因此最后的结果也一定可以为0.但是我的方法和这个不是完全一致,应该说有些升级吧。就是我先判断所有的数字总和,假如和为0,那我不需要操作任何数字,每一个数字都是单独的区间,这样就可以满足条件。假如和为2,那说明1这个数字过多,所以要消除一些1,因此,只要把1放在第二位也就是变成-1,这样整体的值就会减少2,其他的再单独区间输出即可。负数也类似。这样的话需要输出的区间个数也比较好算n-(多的部分)+(多的部分)/ 2 = n-(多的部分)/ 2。
#include<bits/stdc++.h>
using namespace std;
int num[200006];//存储数组列表
int main()
{
int n,k;cin >> n;
while (n--)
{
cin >> k;
int sum = 0;//求和
for (int i = 1;i<=k;i++)
{
int x;
cin >> x;
num[i]=x;
sum+=x;
}
if (k&1)//奇数直接跳出此次
{
cout << "-1\n";
continue;
}
int flag = 1;//为正数
if (sum<0) flag= 0;
int t = abs(sum)/2;
int h = 0;
cout << k-t<<"\n";
for (int i = 1;i<=k;i++)
{
if(flag)//正数多 需要消除 两两小
{
if(num[i+1]==1 && i+1<=k && h!=t) //还需要判断达到t组就结束了
{
cout << i << " " << i+1 <<"\n";
h++;
i++;
}else cout<< i << " " << i <<"\n";
}else
{
if(num[i+1]==-1 && i+1<=k && h!=t)
{
cout << i << " " << i+1 <<"\n";
h++;
i++;
}else cout << i << " " << i <<"\n";
}
}
}
return 0;
}
C2题的话,就是数组里面的数字增加了一个0,然后还是判断最后的区间和是否可以为0。样例稍微有点不一样。
解决的方法和上面的可以说是一致的,还是先加上所有的数字判断和。假如和为奇数,则必然不可能,为偶数,则必然可以。然后下面的分析也就一致了,得出其偏离的程度,然后再划分区间。
#include<bits/stdc++.h>
using namespace std;
int num[200006];
int main()
{
int n,k;cin >> n;
while (n--)
{
cin >> k;
int sum = 0;
for (int i = 1;i<=k;i++)
{
int x;
cin >> x;
num[i]=x;
sum+=x;
}
int flag = 1;//为正数
if (sum<0) flag= 0;
if (sum&1) //唯一改变的地方
{
cout <<"-1\n";
continue;
}
int t = abs(sum)/2;
int h = 0;
cout << k-t<<"\n";
for (int i = 1;i<=k;i++)
{
if(flag)//正数多 需要消除 两两小
{
if(num[i+1]==1 && i+1<=k && h!=t)
{
cout << i << " " << i+1 <<"\n";
h++;
i++;
}else cout<< i << " " << i <<"\n";
}else
{
if(num[i+1]==-1 && i+1<=k && h!=t)
{
cout << i << " " << i+1 <<"\n";
h++;
i++;
}else cout << i << " " << i <<"\n";
}
}
}
return 0;
}
D题的意思就是下面的所有数字的阶乘和是否可以整除上面的x的阶乘,也很简单就两个结论。
1. n! = (n-1)! * n .这就涉及到了进化理论 低层次的可以逐步进化到高阶段
2. n! /(n-1)! = k 高段位阶乘可以整除比他小的段位阶乘,因此相当于最后进化的那个阶乘要大于x!
#include <bits/stdc++.h>
using namespace std;
int main()
{
int n,x;cin >> n >> x;
map<int,int> mp;
int flag = 0;
while (n--)
{
int t;cin >> t;
if (mp.count(t)==0)
{
mp[t] = 1;
}else mp[t]++;
//统计每个数字出现的频率 准备进化
}
for(int i = 1;i<x;i++)
{
int temp = mp[i]/(i+1);//可以进化的次数
if (mp[i] != temp * (i+1)) flag = 1;
if (mp.count(i+1)==0)
{
mp[i+1] = temp;
}else mp[i+1]+=temp;
}
if(flag) cout <<"No";
else cout <<"Yes";
return 0;
}
总结一下就是,读题太慢,搞不太明白,要不然可以快好多。