A - Adventure Time
题意:给一段长度为n(1<=n<=10^5)的字符串和k(1<=k<=26),字符串由a-z构成。求满足字符串有且仅存在k个互异字母时的最大长度的组合数有多少。
eg:input : ababac 2; output : 5 1
满足字符串有且仅存在k个互异字母的字符串有:aaabb,aaac,bbc,aabb,aac....可得最大长度为5且组合数为1
题解:
统计a-z各个字母在原字串中的个数并排序,最后做个组合数就可以了。细节注意:当字串中不存在k个互异字母时输出n 1即可。
AC代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int main(){
int chara[26], Count = 0, k;
long long c[30][30];
string s;
memset(chara, 0, sizeof(chara));
memset(c, 0, sizeof(c));
c[0][0]=1;//c的第一维是从m个数中取,第二维是取n个
for(int i=1;i<=26;i++)
{
c[i][0]=1;
for(int j=1;j<=i && j <= 26;j++)
c[i][j]=(c[i-1][j]+c[i-1][j-1]);
}
cin >> s >> k;
for(int i = 0; i < s.length(); i++){
chara[s[i]-97]++;
}
sort(chara, chara+26);
for(int i = 25; i > 25-k; i--){
Count+=chara[i];
}
if(chara[25-k+1] == 0){
cout << Count << " " << 1 << endl;
return 0;
}
int k1 = 0, k2 = 0;
for(int i = 25-k+1; i < 26; i++){
if(chara[25-k+1] == chara[i])k1++;
else break;
}
for(int i = 25-k; i >= 0; i--){
if(chara[25-k+1] == chara[i])k2++;
else break;
}
cout << Count << " " << c[k1+k2][k1] << endl;
return 0;
}
B - Line Fighting
题意:共有T组测试数据(1<=T<=10),每组数据输入n,k(2<=k<=n<=10^4)。表示n个人,划分成k个队伍。不同队伍选手两两战斗。求最大化的战斗次数。
eg: n = 6 k = 3;
最大化可以划分为每个队伍均有两个人。则战斗次数为A队伍与B队伍有4次对决,A队伍与C队伍有4次对决,B队伍与C队伍有4次对决。合计结果为12次对决。
题解:
每个case尽可能使每个队伍间成员数平均,求战斗数即可
AC代码
#include<iostream>
#include<cstdio>
using namespace std;
int main(){
int T;
cin >> T;
while(T--){
int n, k;
cin >> n >> k;
int x = n/k, y = n%k;
int z = k-y;
long long res = 0;
for(int i = 1; i <= y; i++){
res += (x+1)*(n-i*(x+1));
}
for(int i = y+1; i <= k; i++){
res += x*(n-(x+1)*y-(i-y)*x);
}
cout << res << endl;
}
return 0;
}
C - Dean and Schedule
题意:给出一段长度为n(1<=n<=10^5)的字符串其包含a-z和?,可以对将?修改为a-z任意一个字符。字母存在质量划分,规定a=1,b=2,...,z=26,并且但在字符串偶数位时其质量不计。再给出一个整数k(1<=k<=26)代表字符串中至少存在k个互异的字母,当原字符串不存在k个互异字母,可由修改?使其达到目标。若修改任未能满足要求则输出-1,反之出输出质量最高的字符串。
题解:
遍历一遍字符串统计互异字母个数与?个数的和。若k减去其和为正则无解输出-1,反之有解。
先将字符串填补至k个互异字母(满足偶数位由a开始向上填补,奇数位满足由z向下开始填补)。之后将剩余部分偶数位填入a,奇数位填入z。
AC代码
#include<iostream>
#include<cstdio>
#include<queue>
#include<set>
#include<cmath>
using namespace std;
int main(){
string s;
int n, Count = 0;
queue<int> s1, s2;
set<char> s3;
cin >> s >> n;
for(int i = 0; i < s.length(); i++){
if(s[i] == '?' && i%2==1){
s2.push(i);
Count+=1;
}
else if(s[i] == '?'){
s1.push(i);
Count+=1;
}
else{
s3.insert(s[i]);
}
}
if(n-(int)s3.size()-Count > 0){
cout << "-1" << endl;
}
else if(Count == 0){
cout << s << endl;
}
else{
char ch1 = 'z', ch2 = 'a';
int i = 0;
while(s3.size() < n && ++i){
if(i%2 && !s1.empty()){
if(s3.find(ch1) == s3.end()){
s[s1.front()] = ch1;
s1.pop();
s3.insert(ch1);
}
ch1--;
}
else if(!s2.empty()){
if(s3.find(ch2) == s3.end()){
s[s2.front()] = ch2;
s2.pop();
s3.insert(ch2);
}
ch2++;
}
}
while(!s1.empty()){
s[s1.front()] = 'z';
s1.pop();
}
while(!s2.empty()){
s[s2.front()] = 'a';
s2.pop();
}
cout << s << endl;
}
return 0;
}
D - URCAPL, Episode 1
题意:一门语言给出一套规则,要求写出该语言的解释器
题解:水题
AC代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
const int maxn = 1000;
int n, m, k, arr[1000000];
char map[maxn][maxn];
int Set[10000];
void solve(){
int pos = 1, Pos = 0;//规定1为向右2为向下3为向左4为向上
int x = 0, y = 0, current = 0, times = 0;
while(true){
if(map[x][y] == '>') pos = 1;
else if(map[x][y] == 'v') pos = 2;
else if(map[x][y] == '<') pos = 3;
else if(map[x][y] == '^') pos = 4;
else if(map[x][y] == '+') current+=1;
else if(map[x][y] == '-') current-=1;
else if(map[x][y] == '.'){}
else if(map[x][y]=='?'){
if(Pos == k) current = arr[k-1];
else current = arr[Pos++];
}
else if(map[x][y] == '!'){
cout << current << endl;
current = 0;
}
else if(map[x][y] == '@'){
if(current==0){
pos--;
if(pos == 0) pos = 4;
}
else{
pos++;
if(pos == 5) pos = 1;
}
}
else if('A' <= map[x][y] && map[x][y] <= 'Z'){
swap(Set[map[x][y]], current);
}
else if(map[x][y] == '#'){
break;
}
if(abs(current) > 100000){
cout << "OVERFLOW ERROR" << endl;
break;
}
if(pos == 1) y+=1;
else if(pos == 2) x+=1;
else if(pos == 3) y-=1;
else if(pos == 4) x-=1;
if(x<0||y<0||x>=n||y>=m){
cout << "RUNTIME ERROR" << endl;
break;
}
times++;
if(times >= 1000000){
cout << "TIME LIMIT EXCEEDED" << endl;
break;
}
}
}
int main(){
cin >> n >> m;
memset(Set, 0, sizeof(Set));
for(int i = 0; i < n; i++){
cin >> map[i];
}
cin >> k;
for(int i = 0; i < k; i++)
cin >> arr[i];
solve();
return 0;
}
E - URCAPL, Episode 2
题意:由D题给出的语言写出,1+....+n的结果。
弱鸡没写出来
F - Towers of Hanoi Strike Back
题意:汉诺塔问题。输入n(1<=n<=50),第二行输入长度为n的字符串(仅包含ABC)。ABC分别代表3根柱子。要求盘子按照字符串给出的位置放置,每个盘子的编号为下标+1。所有盘子最开始在A柱子上,求最小移动盘子的步数。
题解:
设ch为未放置规定位置的盘子所在位置。由未放置规定位置的盘子的最底层盘子开始。最底层盘子若要移动到规定位置,其最小步数为2^m(m为底层盘子往上的盘子数目)。注意,若扫描到的盘子已在规定位置则跳过计算。
AC代码
#include<iostream>
#include<cstdio>
using namespace std;
int main(){
long long res[51];
long long k = 0;
int n;
string str;
cin >> n >> str;
res[0] = 0;
res[1] = 0;
res[2] = 1;
for(int i = 3; i <= 50; i++){
res[i] = res[i-1]*2+1;
}
char ch = 'A';
for(int i = n-1; i >= 0; i--){
if(str[i]!=ch){
k+=res[i+1]+1;
if(ch == 'A' && str[i] == 'B') ch = 'C';
else if(ch == 'A' && str[i] == 'C') ch = 'B';
else if(ch == 'B' && str[i] == 'A') ch = 'C';
else if(ch == 'B' && str[i] == 'C') ch = 'A';
else if(ch == 'C' && str[i] == 'A') ch = 'B';
else if(ch == 'C' && str[i] == 'B') ch = 'A';
}
}
cout << k << endl;
return 0;
}
G - Awesome Backup System
弱鸡还没解出来
H - Overturned Numbers
题意:0、1、8的数翻转180°后仍为本身,6翻转180°后变为9,其余数不能翻转。输入n(1<=n<=99)求n个翻转后连续的序列,仅使用一位整数只补充前导0和两位整数。若没有此序列则输出“Glupenky Pierre”,若存在则输出序列。
题解:
水题。6翻转后变为9且0、1、8翻转后是其本身。则可看出连续序列最大为4。x8、x9、(x+1)0、(x+1)1。
AC代码
#include<iostream>
#include<cstdio>
using namespace std;
int main(){
char ch[5][3] = {"16","06","68","88","86"};
int n;
cin >> n;
if(n>4)cout << "Glupenky Pierre" << endl;
else{
for(int i = 0; i < n; i++){
cout << ch[i] << " ";
}
cout << endl;
}
return 0;
}
I - Conspiracy Theory and Rebranding
题意:给出三角形三条边长度,求出在笛卡尔坐标系下的整数坐标解,若无解则输出-1。
题解:
以原点为三角形的一个坐标点。对其中两条边以原点以其边长为半径画圆。以其两圆上的整数坐标一一判断是否能构成第三边边长,可以则得出结果。否则输出-1。
AC代码
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<vector>
using namespace std;
struct rg{
int x, y;
rg(int x = 0, int y = 0):x(x),y(y){}
};
int main(){
int ragc[3], dir[4][2] = {{1,1},{-1,1},{1,-1},{-1,-1}};
cin >> ragc[0] >> ragc[1] >> ragc[2];
vector<rg> B;
B.clear();
for(int j = 0; j <= ragc[1]; j++){
long long k1 = 1ll*ragc[1]*ragc[1]-1ll*j*j;
int k2 = sqrt(k1+0.0);
if(1ll*k2*k2 != k1)continue;
B.push_back(rg(j, k2));
}
for(int i = 0; i <= ragc[0]; i++){
long long k1 = 1ll*ragc[0]*ragc[0]-1ll*i*i;
int k2 = sqrt(k1+0.0);
if(1ll*k2*k2 != k1) continue;
for(int j = 0; j < B.size(); j++){
for(int k = 0; k < 4; k++){
int x1 = i*dir[k][0], y1 = k2*dir[k][1];
long long l = 1ll*(x1-B[j].x)*(x1-B[j].x)+1ll*(y1-B[j].y)*(y1-B[j].y);
if(l != 1ll*ragc[2]*ragc[2])continue;
cout << "0 0" << endl;
cout << x1 << " " << y1 << endl;
cout << B[j].x << " " << B[j].y << endl;
return 0;
}
}
}
cout << -1 << endl;
return 0;
}
J - Devices
题意:求被推荐设备最多且设备价格最低的设备名称。
题解:模拟题,水一下就过了。
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
struct frinds{
char shebei[30];
int value;
int num;
}queue[6];
int main(){
int k = 0;
for(int i = 0; i < 6; i++) queue[i].num = 0;
for(int i = 0; i < 6; i++){
char a[30], b[30];
int c, chack = 0;
cin >> a >> b >> c;
for(int j = 0; j < k; j++){
if(!strcmp(b, queue[j].shebei)){
queue[j].num++;
queue[j].value = min(queue[j].value, c);
chack = 1;
break;
}
}
if(!chack){
strcpy(queue[k].shebei, b);
queue[k].num = 1;
queue[k].value = c;
k++;
}
}
int value = 1000000, times = 0;
char res[30] = "";
for(int i = 0; i < k; i++){
if(times < queue[i].num){
memset(res, 0, sizeof(res));
strcpy(res, queue[i].shebei);
value = queue[i].value;
times = queue[i].num;
}
else if(times == queue[i].num && value > queue[i].value){
memset(res, 0, sizeof(res));
strcpy(res, queue[i].shebei);
value = queue[i].value;
times = queue[i].num;
}
}
cout << res << endl;
return 0;
}
K - Caravans
弱鸡还没解出来
L - Another Dress Rehearsal
题意:给出A、B、C三个值要求在A区间取一个数,在B区间取一个数,其和为C。
题解:
水题。比赛时想智障想复杂了,用两次二分过了。
AC代码
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
struct frinds{
char shebei[30];
int value;
int num;
}queue[6];
int main(){
int k = 0;
for(int i = 0; i < 6; i++) queue[i].num = 0;
for(int i = 0; i < 6; i++){
char a[30], b[30];
int c, chack = 0;
cin >> a >> b >> c;
for(int j = 0; j < k; j++){
if(!strcmp(b, queue[j].shebei)){
queue[j].num++;
queue[j].value = min(queue[j].value, c);
chack = 1;
break;
}
}
if(!chack){
strcpy(queue[k].shebei, b);
queue[k].num = 1;
queue[k].value = c;
k++;
}
}
int value = 1000000, times = 0;
char res[30] = "";
for(int i = 0; i < k; i++){
if(times < queue[i].num){
memset(res, 0, sizeof(res));
strcpy(res, queue[i].shebei);
value = queue[i].value;
times = queue[i].num;
}
else if(times == queue[i].num && value > queue[i].value){
memset(res, 0, sizeof(res));
strcpy(res, queue[i].shebei);
value = queue[i].value;
times = queue[i].num;
}
}
cout << res << endl;
return 0;
}