A AquaMoon and Two Arrays
题目大意
给两个长度为n的数组,问a数组是否能通过给一个数+1,另一个数-1操作变成数组b,如果能输出操作步数且打印方案
主要思路
如果suma == sumb那么一定能变成,用st数组记录每个ai - bi的值,所有st数组中大于0的值的和就是操作步数,然后再用两个指针一个指向st中的负数,一个指向st中的正数,输出即可
AC代码
#include <iostream>
#include <cstring>
#include <string>
#include <algorithm>
#include <stack>
#include <string>
#include <cmath>
#include <unordered_map>
#include <queue>
#include <map>
using namespace std;
#define int long long
#define debug(a) cout << #a << " = " << a << endl;
#define x first
#define y second
typedef pair<int, int> P;
const int N = 200010;
int n, a[N], b[N];
int st[N];
signed main(void)
{
int T;
cin >> T;
while(T--)
{
cin >> n;
int suma = 0, sumb = 0;
int cnt = 0;
for(int i = 0; i < n; i++) cin >> a[i], suma += a[i];
for(int i = 0; i < n; i++)
{
cin >> b[i];
st[i] = a[i] - b[i];
sumb += b[i];
if(st[i] > 0) cnt += st[i];
}
if(suma != sumb)
{
puts("-1");
}
else
{
int pos1 = -1, pos2 = -1;
for(int i = 0; i < n; i++)
{
if(st[i] < 0 && pos1 == -1) pos1 = i;
if(st[i] > 0 && pos2 == -1) pos2 = i;
if(pos1 != -1 && pos2 != -1)
{
break;
}
}
cout << cnt << endl;
while(pos1 < n || pos2 < n)
{
while(st[pos1] >= 0 && pos1 < n) pos1++;
while(st[pos2] <= 0 && pos2 < n) pos2++;
if(pos1 < n && pos2 < n && st[pos1] < 0 && st[pos2] > 0)
{
cout << pos2 + 1 << ' ' << pos1 + 1 << endl;
st[pos1]++, st[pos2]--;
}
}
}
}
return 0;
}
B AquaMoon and Stolen String
题目大意
给定n个长度为m的字符串,再给n-1个长度为m的字符串,其中n - 1个字符串是由n个字符串中的n-1个交换每个位置上的元素得到,问n个字符串中没有参与交换的是哪个
主要思路
统计每一列中某个字母的个数,如果某一行的所有字母在每一列中都是奇数 那么这一行就是答案
#include <iostream>
#include <cstring>
#include <string>
#include <algorithm>
#include <stack>
#include <string>
#include <cmath>
#include <unordered_map>
#include <queue>
#include <map>
using namespace std;
#define int long long
#define debug(a) cout << #a << " = " << a << endl;
#define x first
#define y second
typedef pair<int, int> P;
const int N = 100010;
int n, m;
int st[N][30];
string s[N];
signed main(void)
{
int T;
cin >> T;
while(T--)
{
cin >> n >> m;
memset(st, 0, sizeof(st));
for(int i = 0; i < n; i++)
{
cin >> s[i];
for(int j = 0; j < m; j++)
{
st[j][s[i][j] - 'a']++;
}
}
for(int i = 0; i < n - 1; i++)
{
string s;
cin >> s;
for(int j = 0; j < m; j++)
{
st[j][s[j] - 'a']++;
}
}
for(int i = 0; i < n; i++)
{
bool flag = true;
for(int j = 0; j < m; j++)
{
if(st[j][s[i][j] - 'a'] % 2 == 0)
{
flag = false;
break;
}
}
if(flag)
{
cout << s[i] << endl;
break;
}
}
}
return 0;
}
C AquaMoon and Strange Sort
题目大意
给定一个长度为n的数组,刚开始每个元素都指向右,每次交换相邻两个元素都会是元素指向改变,问能否给该数组排序,同时使最后所有元素还是都指向右
主要思路
每个元素都交换两次才能保证最后每个元素还是指向右边,那么开始在奇数位置的元素还在奇数位置,开始在偶数位置的元素还在偶数位置,那么我们把奇数位置元素记下,偶数元素位置元素记下,直接对原数组排序,如果奇数位置还是那些数,则说明能该边,如果奇数位置不是原来那些数,则说明不能改变
AC代码
#include <iostream>
#include <cstring>
#include <string>
#include <algorithm>
#include <stack>
#include <string>
#include <cmath>
#include <unordered_map>
#include <queue>
#include <map>
using namespace std;
#define int long long
#define debug(a) cout << #a << " = " << a << endl;
#define x first
#define y second
typedef pair<int, int> P;
const int N = 100010;
int n, a[N];
int f[2][N];
signed main(void)
{
int T;
cin >> T;
while(T--)
{
memset(f, 0, sizeof(f));
cin >> n;
for(int i = 0; i < n; i++)
{
cin >> a[i];
f[i % 2][a[i]]++;
}
sort(a, a + n);
for(int i = 0; i < n; i++)
{
f[i % 2][a[i]]--;
}
bool flag = true;
for(int i = 0; i < N; i++)
{
if(f[0][i] || f[1][i])
{
flag = false;
break;
}
}
if(flag) puts("YES");
else puts("NO");
}
return 0;
}
D AquaMoon and Chess
题目大意
给你一个0 1串,1只能隔一个1跳到相邻位置的0(象棋的炮), 问有多少种排列方式
主要思路
1的移动是以11为单位,因此我们可以计算出有多少个11,和计算出有多少个0,相当于n个相同的球放进m个盒子中,且允许空箱,那么答案就为C(n + m - 1, m - 1),m为1可以在0中插入的位置个数,也就是0的个数+1
不同情况组合数公式见:https://blog.csdn.net/u012720552/article/details/80961684
AC代码
#include <iostream>
#include <cstring>
#include <string>
#include <algorithm>
#include <stack>
#include <string>
#include <cmath>
#include <unordered_map>
#include <queue>
#include <map>
using namespace std;
#define int long long
#define debug(a) cout << #a << " = " << a << endl;
#define x first
#define y second
typedef pair<int, int> P;
const int N = 100010, mod = 998244353;
int n;
int qmi(int a, int k, int p) // 快速幂模板
{
int res = 1 % p;
while (k)
{
if (k & 1) res = res * a % p;
a = a * a % p;
k >>= 1;
}
return res;
}
int C(int a, int b, int p) // 通过定理求组合数C(a, b)
{
if (a < b) return 0;
int x = 1, y = 1; // x是分子,y是分母
for (int i = a, j = 1; j <= b; i --, j ++ )
{
x = x * i % p;
y = y * j % p;
}
return x * qmi(y, p - 2, p) % p;
}
int lucas(int a, int b, int p)
{
if (a < p && b < p) return C(a, b, p);
return (int)C(a % p, b % p, p) * lucas(a / p, b / p, p) % p;
}
signed main(void)
{
int T;
cin >> T;
while(T--)
{
cin >> n;
string s;
cin >> s;
int a = 0, b = 0;
for(int i = 0; i < n; i++)
{
if(s[i] == '0') a++;
else
{
int cnt = 0;
while(s[i] == '1')
{
cnt++;
i++;
}
b += cnt / 2;
i--;
}
}
a++;
cout << lucas(a + b - 1, a - 1, mod) << endl;
}
return 0;
}