A Foreover
热身题,结合求最大公约数、检查是否为素数、DFS回溯,很综合的一道题目,注意剪枝,否则数据过大可能会TLE。
#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
#define ac cin.tie(0);cin.sync_with_stdio(0);
using namespace std;
string s;
//n和A
typedef pair<int, string> PAIR;
vector<PAIR> ans;
int n, k, m;
//按照题目输出顺序排序
bool cmp(const PAIR &a, const PAIR &b) {
if (a.first != b.first)
return a.first < b.first;
else
return a.second < b.second;
}
//返回最大公约数
long long gcd(int a, int b) {
return b == 0 ? a : gcd(b, a % b);
}
//检查是否为素数
bool check(int a) {
if (a <= 2)
return false;
for (int i = 2; i * i <= a; i++)
if (a % i == 0)
return false;
return true;
}
//求解
void dfs(int lev, int res) {
if (lev == k) {
if (!res) {
long long tmp = stoll(s) + 1;
int nn = 0;
while (tmp) {
nn += tmp % 10;
tmp /= 10;
}
if (check(gcd(nn, m)))
ans.push_back(PAIR(nn, s));
}
return;
}
//剪枝
if (res > 9 * (k - lev) || res < 0)
return;
for (int i = 0; i <= 9; i++) {
if (lev == 0 && i == 0)
continue;
s.push_back('0' + i);
res -= i;
dfs(lev + 1, res);
s.pop_back();
res += i;
}
}
int main() {
ac
cin >> n;
for (int i = 1; i <= n; i++) {
ans.clear();
cout << "Case " << i << endl;
cin >> k >> m;
dfs(0, m);
if (ans.size()) {
sort(ans.begin(), ans.end(), cmp);
for (PAIR i:ans)
cout << i.first << " " << i.second << endl;
} else
cout << "No Solution\n";
}
return 0;
}
B Merging Linked Lists
一道很好的数据结构链表的考题,细心即可。
#include<cstdio>
#include<algorithm>
using namespace std;
const int MAXN = 100010;
int val[MAXN], nxt[MAXN];
int head1, head2;
int n;
int main() {
int a;
scanf("%d %d %d", &head1, &head2, &n);
while (n--) {
scanf("%d", &a);
scanf("%d %d", &val[a], &nxt[a]);
}
int cnt1 = 0, cnt2 = 0, tmp = head1;
while (tmp != -1) {
++cnt1;
tmp = nxt[tmp];
}
tmp = head2;
while (tmp != -1) {
++cnt2;
tmp = nxt[tmp];
}
//确定那个链表长、那个链表短,使得L1永远是长的那个
if (cnt1 < cnt2)
swap(head1, head2);
//Reverse L2
int pre = -1;
tmp = head2;
while (tmp != -1) {
int nxx = nxt[tmp];
nxt[tmp] = pre;
pre = tmp;
tmp = nxx;
}
head2 = pre;
//保留头指针
tmp = head1;
while (head1 != -1 && head2 != -1) {
//跳过一个L1节点
head1 = nxt[head1];
//如果到末尾则跳出
if (head1 == -1)
break;
//保留L2的下一个节点,因为要操作L2的next指针
int nxx = nxt[head2];
//这两步把L2插入L1
nxt[head2] = nxt[head1];
nxt[head1] = head2;
//L2重新取得原本该下一个的指针
head2 = nxx;
//两次next就为原本的L1下一个
head1 = nxt[head1];
head1 = nxt[head1];
}
//输出
while (tmp != -1) {
if (nxt[tmp] != -1)
printf("%05d %d %05d\n", tmp, val[tmp], nxt[tmp]);
else
printf("%05d %d -1\n", tmp, val[tmp]);
tmp = nxt[tmp];
}
return 0;
}
C Postfix Expression
二叉树,较简单,DFS。
#include<iostream>
#include<string>
#define ac cin.tie(0);cin.sync_with_stdio(0);
using namespace std;
const int MAXN = 30;
int le[MAXN], ri[MAXN];
string val[MAXN];
bool vis[MAXN];
int n, root;
void dfs(int root) {
if (root == -1)
return;
cout << "(";
//注意题目陷阱,只有左子树或者右子树operator要提前
if (le[root] != -1 && ri[root] != -1) {
dfs(le[root]);
dfs(ri[root]);
cout << val[root] << ")";
} else {
cout << val[root];
dfs(le[root]);
dfs(ri[root]);
cout << ")";
}
}
int main() {
ac
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> val[i] >> le[i] >> ri[i];
if (le[i] >= 1)
vis[le[i]] = true;
if (ri[i] >= 1)
vis[ri[i]] = true;
}
//find root
for (int i = 1; i <= n; i++)
if (!vis[i]) {
root = i;
break;
}
dfs(root);
return 0;
}
Dijikstra Sequence
PAT图论模板题。
#include<iostream>
#include<cstring>
#include<algorithm>
#define ac cin.tie(0);cin.sync_with_stdio(0);
using namespace std;
const int MAXN = 1010;
int G[MAXN][MAXN], dist[MAXN], arr[MAXN];
bool vis[MAXN];
int n, m, k;
//PAT式迪杰斯特拉算法
bool solve() {
memset(dist, 0x3f, sizeof(dist));
memset(vis, false, sizeof(vis));
dist[arr[1]] = 0;
int cnt = 1;
for (int i = 1; i <= n; i++) {
int k = -1;
for (int j = 1; j <= n; j++)
if (!vis[j] && (k == -1 || dist[j] < dist[k]))
k = j;
//判断是否合法
if (dist[k] != dist[arr[cnt++]])
return false;
vis[k] = true;
for (int j = 1; j <= n; j++) {
if (vis[j])
continue;
if (dist[j] > dist[k] + G[k][j])
dist[j] = dist[k] + G[k][j];
}
}
return true;
}
int main() {
ac
int a, b, c;
memset(G, 0x3f, sizeof(G));
cin >> n >> m;
while (m--) {
cin >> a >> b >> c;
G[a][b] = G[b][a] = c;
}
cin >> k;
while (k--) {
for (int i = 1; i <= n; i++)
cin >> arr[i];
if (solve())
cout << "Yes";
else
cout << "No";
if (k)
cout << endl;
}
return 0;
}