目录
A. Game with Cards
B. Card Trick
C. Double Sort
D. Required Length
A. Game with Cards
题目大意: Alice 和 Bob打牌,每人有若干牌,一共比两局,第一局Alice先手,第二局Bob先手
每回合打一张牌,若B没有比A出的牌大的牌,则此局A胜,反之,B胜
思路:两个人每局第一回合就出最大的牌,一局定胜负
代码如下:
#include
using namespace std;
typedef pair PII;
typedef long long LL;
const int N = 2e5+10;
int T;
void solve()
{
int n, m;
int x, a = 0, b = 0;
scanf("%d", &n);
for(int i = 0; i < n; i ++ )
scanf("%d", &x), a = max(a, x);
scanf("%d", &m);
for(int i = 0; i < m; i ++ )
scanf("%d", &x), b = max(b, x);
// Alice 1 Bob 2
if(a > b)
{
puts("Alice");
puts("Alice");
return;
}
else if(b > a)
{
puts("Bob");
puts("Bob");
return;
}
else
{
puts("Alice");
puts("Bob");
return;
}
return;
}
int main()
{
scanf("%d", &T);
while(T -- )
solve();
return 0;
}
B. Card Trick
题目翻译:给定数组a,每次操作为给一个数 x ,将 x 之上元素按照原次序放到数组的末端,经过b次操作,问:输出数组最上方的元素
思路:我们模拟样例可知,此操作的方法类似于循环数组,设置一个 top 表示 top 为最上方元素的索引,top 初值为 n - 1,因为原数组反序为卡牌的正序,即,a[n-1] 为 最上方的值
举例:x = 1,原题意为,将 n-1 移到最下方,即,n-1-x 位置的元素为最上方元素,等效于将 top-=x,依据如此思路,我们每次输入的 x 都令top减去 x ,若top不够减,则令返回到 n 继续减
代码如下:
#include
using namespace std;
typedef pair PII;
typedef long long LL;
const int N = 2e5+10;
int T;
void solve()
{
int n, m;
int a[N], b[N];
int x;
scanf("%d", &n);
int v[n+10], vt[n+10];
for(int i = 0; i < n; i ++ )
scanf("%d", &a[i]);
int cnt = 0;
for(int i = n-1; i >= 0; i -- )
v[cnt++] = a[i];
int t = n-1;
scanf("%d", &m);
for(int i = 0; i < m; i ++ )
{
scanf("%d", &x);
if(t - x < 0) t = n - ( x - t );
else t -= x;
}
cout << v[t] << endl;
return;
}
int main()
{
scanf("%d", &T);
while(T -- )
solve();
return 0;
}
C. Double Sort
题目翻译:给定两数组,两数组关联(a[i] 与 a[j] 交换,同时 b[i] 与 b[j] 也交换),将a数组非降序排列的同时,使b数组也排列为非降序排列,并且交换次数不大于 1e4
思路:冒泡排序即可,交换a数组时记得交换b数组就行,重要的是,特判以下,当两a数组的元素相等时,b数组的此位置的两元素是否相等,根据情况选择交换还是不交换b数组的两元素,因为a数组的两元素相等,交换不交换是一样的,
代码如下:
#include
using namespace std;
typedef pair PII;
typedef long long LL;
const int N = 2e5+10;
int T;
void solve()
{
int n, m;
int a[N], b[N];
int x;
scanf("%d", &n);
for(int i = 1; i <= n; i ++ )
scanf("%d", &a[i]);
for(int i = 1; i <= n; i ++ )
scanf("%d", &b[i]);
vector v;
for(int i = 1; i <= n; i ++ )
{
for(int j = i+1; j <= n; j ++ )
{
if(a[i] > a[j]) swap(a[i], a[j]), swap(b[i], b[j]), v.push_back({i, j});
else if(a[i] == a[j] && b[i] > b[j]) swap(b[i], b[j]), v.push_back({i, j});
}
}
int f = 1;
for(int i = 2; i <= n; i ++ )
if(b[i] < b[i-1]) f = 0;
if(f && v.size() < 1e4)
{
cout << v.size() << endl;
for(auto it : v)
cout << it.first << " " << it.second << endl;
}
else cout << -1 << endl;
return;
}
int main()
{
scanf("%d", &T);
while(T -- )
solve();
return 0;
}
D. Required Length
题目翻译:给定n, m,每次从m中取一位数与m相乘,问最多取几次可以使,m 的长度等于n
思路:貌似和走迷宫的最短路有点像,直接BFS就可,我们要查找最小的成立次数,BFS可以保持次数为从小到大的顺序,DFS不能确定找到的为最小值,但DFS也能找到一个值,只不过不一定是题目需要的最小值
小技巧:
数字转化为字符串(此处有详解)
(1)string s = to_string(数字变量)(2)stringstream
代码如下:
#include
using namespace std;
typedef pair PII;
typedef long long LL;
const int N = 30;
int T;
void solve()
{
return;
}
int main()
{
LL n, m;
scanf("%lld %lld", &n, &m);
queue q;
map dist;
dist[m] = 0;
q.push(m);
while(q.size())
{
LL t = q.front();
q.pop();
string s;
stringstream ss;
ss << t;
ss >> s;
//cout << t << endl;
if(s.size() == n)
{
printf("%d\n", dist[t]);
return 0;
}
for(int i = 0; i < s.size(); i ++ )
{
if(s[i] == '0') continue;
LL w = t * int(s[i] - '0');
if(!dist.count(w))
{
//cout << w << endl;
dist[w] = dist[t] + 1;
q.push(w);
}
}
}
puts("-1");
return 0;
}