A题-Carryless Square Root
- 题意:
对于不进位的乘法,要求找到最小的满足该条件的数字
贪心dfs从最高位到最低位,数字从最小到最大
const int N = 1e2 + 10;
string s;
int len, ans[N], num[N], sum[N];
int check(int pos)
{
memset(sum, 0, sizeof sum);
for (int i = 0; i <= pos; i++)
for (int j = 0; j <= pos; j++)
{
sum[i + j] = sum[i + j] + (ans[i] * ans[j]) % 10;
sum[i + j] %= 10;
}
if (pos == len - 1)
pos = s.size();
for (int i = 0; i < pos; i++)
if (sum[i] != num[i])
return 0;
return 1;
}
void dfs(int pos)
{
if (pos == len)
{
for (int i = 0; i < len; i++)
cout << ans[i];
cout << endl;
exit(0);
}
for (int i = 0; i < 10; i++)
{
ans[pos] = i;
if (check(pos))
dfs(pos + 1);
}
}
signed main()
{
cin >> s;
int n = s.size();
if (n % 2)
{
for (int i = 0; i < n; i++)
num[i] = s[i] - '0';
len = n / 2 + 1;
dfs(0);
cout << -1 << endl;
}
else
cout << -1 << endl;
return 0;
}
D题-Swap Free
- 题意:
寻找可以 无法 通过一次交换而产生相同字符串的最大数量的集合
旭压力算法板子题
const int N = 5e2 + 10;
vector<int> a[N];
string s[N];
int vis[N], n, match[N];
int dfs(int u)
{
int m = a[u].size();
for (int i = 0; i < m; i++)
if (!vis[a[u][i]])
{
vis[a[u][i]] = 1;
if (!match[a[u][i]] || dfs(match[a[u][i]]))
{
match[a[u][i]] = u;
return 1;
}
}
return 0;
}
signed main()
{
cin >> n;
for (int i = 1; i <= n; i++)
cin >> s[i];
int len = s[1].size();
for (int i = 1; i <= n; i++)
for (int j = i + 1; j <= n; j++)
{
int f = 0;
for (int k = 0; k < len; k++)
{
if (s[i][k] == s[j][k])
continue;
f++;
if (f > 2)
break;
}
if (f == 2)
{
a[i].push_back(j);
a[j].push_back(i);
}
}
int ans = 0;
for (int i = 1; i <= n; i++)
{
memset(vis, 0, sizeof vis);
if (dfs(i))
ans++;
}
cout << n - ans / 2 << endl;
}
H题-Levenshtein Distance
- 题意:
使用现存字母表中的字母,对给出的字符串可以进行三种操作:
1、替换其中一个字母
2、删除其中一个字母
3、添加其中一个字母
输出所有可以的情况
set<string> ans;
signed main()
{
string s, str;
cin >> s >> str;
int n = str.size();
int m = s.size();
//删除
for (int i = 0; i < n; i++)
{
string c = "";
c += str.substr(0, i);
c += str.substr(i + 1, n);
ans.insert(c);
}
//添加
for (int i = 0; i <= n; i++)
for (int j = 0; j < m; j++)
{
string c = "";
c += str.substr(0, i);
c += s[j];
c += str.substr(i, n);
ans.insert(c);
}
//更改
for (int i = 0; i < n; i++)
for (int j = 0; j < m; j++)
{
string c = "";
c += str.substr(0, i);
c += s[j];
c += str.substr(i + 1, n);
ans.insert(c);
}
for (auto t : ans)
if (t != str)
cout << t << endl;
}
J题-One of Each
- 题意:
给定顺序的n个数字,要求找出字典序最小的从1 ~ m的全排列,保证n个数字中都是从1 ~ m(贪心)
可以发现对于给定的排列数字越大(字典序越大),它的位置应该尽可能的往后,这样才可以形成最优解。这样,利用栈的性质,每次遍历一个数字,就将该数字前面比它大的可以删除的进行删除操作
const int N = 2e5 + 10;
int num[N];
int a[N];
int vis[N];
int tt;
int sta[N];
int flag[N];
signed main()
{
int n, m;
scanf("%d%d", &n, &m);
for (int i = 0; i < n; i++)
{
scanf("%d", &a[i]);
num[a[i]]++;
}
for (int i = 0; i < n; i++)
{
num[a[i]]--;
if (!flag[a[i]])
{
flag[a[i]] = 1;
while (tt && num[sta[tt - 1]] && sta[tt - 1] > a[i])
{
flag[sta[tt - 1]] = 0;
tt--;
}
sta[tt++] = a[i];
}
}
for (int i = 0; i < tt; i++)
printf("%d ",sta[i]);
}
I题-Maze Connect
- 题意:给定一个旋转的迷宫, 要求所有的格中的点都可以出去
就是寻找连通块的个数,不过地图有点狗血,但是可以发现关系就是一个联通图一定是连起来的,就像下面这样
/\
\/
一定会有连接到一起的\/,这样我们可以通过并查集来维护这个关系,如果有一样的集合那么说明就是重合的点,也可以通过搜索的写法,将图扩大两倍。
typedef pair<int, int> PII;
const int N = 1e3 + 10;
char s[N][N];
map<PII, PII> fa;
int ans = 0;
PII find(PII a)
{
if (a != fa[a])
fa[a] = find(fa[a]);
return fa[a];
}
void join(PII a, PII b)
{
PII aa = find(a);
PII bb = find(b);
if (aa != bb)
fa[aa] = bb;
else
ans++;
}
signed main()
{
int n, m;
cin >> n >> m;
for (int i = 1; i <= n; i++)
cin >> s[i] + 1;
for (int i = 0; i <= n + 1; i++)
for (int j = 0; j <= m + 1; j++)
fa[make_pair(i, j)] = make_pair(i, j);
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
if (s[i][j] == '/')
join(make_pair(i, j + 1), make_pair(i + 1, j));
else if (s[i][j] == '\\')
join(make_pair(i, j), make_pair(i + 1, j + 1));
cout << ans << endl;
}