目录
1001 A+B Format
求A+B, 但是输出每隔三位数字加一个",".
void solve() {
int a, b;
cin>>a>>b;
string s = to_string(a + b);
int n = s.size();
int idx = 0;
if(s[0] == '-') idx ++;
int cnt = 0;
string s1;
for(int i = n - 1; i >= 0; i --) {
cnt ++;
s1 += s[i];
if(cnt % 3 == 0 && i > idx) s1 += ',';
}
reverse(s1.begin(), s1.end());
cout<<s1<<endl;
}
1002 A+B for Polynomials
求多项式A+B后每项的系数,需要注意输出需要按照输入形式输出,即项数从大到小,遇到系数为0跳过,保留一位小数.
double mp[1010];
void solve() {
int n;
cin>>n;
for(int i = 0; i < n; i ++) {
int a; double b;
cin>>a>>b;
mp[a] += b;
}
cin>>n;
for(int i = 0; i < n; i ++) {
int a; double b;
cin>>a>>b;
mp[a] += b;
}
int cnt = 0;
for(int i = 0; i <= 1000; i ++) {
if(mp[i] != 0) cnt ++;
}
printf("%d", cnt);
for(int i = 1000; i >= 0; i --) {
if(mp[i] != 0) printf(" %d %.1lf", i, mp[i]);
}
}
1003 Emergency
求出发点到终点的最短路径有多少条以及最大权值是多少.
int n, m, st, ed;
int dist[510];
bool vis[510];
vector<PII> v[510];
int w[510];
int ans[510];
int sum[510];
void solve() {
cin>>n>>m>>st>>ed;
for(int i = 0; i < n; i ++) cin>>w[i];
for(int i = 1; i <= m; i ++) {
int x, y, s;
cin>>x>>y>>s;
v[x].push_back({y, s});
v[y].push_back({x, s});
}
priority_queue<PII, vector<PII>, greater<PII>> q;
memset(dist, 0x3f, sizeof dist);
q.push({0, st});
dist[st] = 0;
ans[st] = w[st];
sum[st] = 1;
while(q.size()) {
auto [d, now] = q.top();
q.pop();
if(vis[now]) continue;
vis[now] = 1;
for(auto k : v[now]) {
if(dist[now] + k.second < dist[k.first]) {
dist[k.first] = dist[now] + k.second;
ans[k.first] = max(ans[k.first], ans[now] + w[k.first]);
q.push({dist[k.first], k.first});
sum[k.first] = sum[now];
}
else if(dist[now] + k.second == dist[k.first]) {
sum[k.first] += sum[now];
q.push({dist[k.first], k.first});
ans[k.first] = max(ans[k.first], ans[now] + w[k.first]);
}
}
}
cout<<sum[ed]<<' '<<ans[ed];
}
1004 Counting Leaves
统计一个森林里每层有多少个叶子节点.
vector<int> v[100];
int n, m;
bool rt[100];
int dep[100], mx;
void dfs(int u, int d) {
int f = 1;
for(auto k : v[u]) {
dfs(k, d + 1);
f = 0;
}
dep[d] += f;
mx = max(mx, d);
}
void solve() {
cin>>n>>m;
int id, k;
while(m --) {
cin>>id>>k;
while(k --) {
int x;
cin>>x;
v[id].push_back(x);
rt[x] = 1;
}
}
for(int i = 1; i <= n; i ++) {
if(!rt[i]) dfs(i, 0);
}
for(int i = 0; i <= mx; i ++) {
cout<<dep[i];
if(i != mx) cout<<' ';
}
}
1005 Spell It Right
输出各数位的英文表示.
map<char, string> mp;
void init() {
mp['0'] = "zero";
mp['1'] = "one";
mp['2'] = "two";
mp['3'] = "there";
mp['4'] = "four";
mp['5'] = "five";
mp['6'] = "six";
mp['7'] = "seven";
mp['8'] = "eight";
mp['9'] = "nine";
}
void solve() {
init();
string s;
cin>>s;
int sum = 0;
int n = s.size();
for(int i = 0; i < n; i ++) sum += s[i] - '0';
s = to_string(sum);
n = s.size();
for(int i = 0; i < n; i ++) {
cout<<mp[s[i]];
if(i != n - 1) cout<<' ';
}
}
1006 Sign In and Sign Out
询问第一个到达的人和最后一个离开的人.
int n;
struct node{
string name, st, ed;
}t;
void solve() {
cin>>n;
vector<node> v;
while(n --) {
string s, s1, s2;
cin>>s>>s1>>s2;
v.push_back({s, s1, s2});
}
sort(v.begin(), v.end(), [&](node a, node b) {return a.st < b.st;});
cout<<v[0].name<<' ';
sort(v.begin(), v.end(), [&](node a, node b){return a.ed > b.ed;});
cout<<v[0].name;
}
1007 Maximum Subsequence Sum
求最大连续区间和以及该区间首尾元素,要求区间左右端点尽可能小。
int n;
ll mx = -1, st = -1, ed = -1, l;
void solve() {
cin>>n;
ll sum = 0;
ll a[n + 1];
for(int i = 0; i < n; i ++) cin>>a[i];
bool f = 1;
for(int i = 0; i < n; i ++) {
if(sum > 0) sum += a[i];
else {
l = a[i];
sum = a[i];
}
if(sum > mx) {
mx = sum;
st = l;
ed = a[i];
}
}
if(mx == -1) mx = 0, st = a[0], ed = a[n - 1];
cout<<mx<<' ';
cout<<st<<' '<<ed;
}
1008 Elevator
模拟上下楼梯。
int n;
int now;
int ans;
void solve() {
cin>>n;
int x;
while(n --) {
cin>>x;
ans += 5;
if(x < now) ans += (now - x) * 4;
else ans += (x - now) * 6;
now = x;
}
cout<<ans;
}
1009 Product of Polynomials
多项式A*B,输出规范和1002一样,相当于B的每一项乘A的每一项再相加
int n;
map<int, double> mp;
map<int, double> ans;
void solve() {
cin>>n;
while(n --) {
int a; double b;
cin>>a>>b;
mp[a] += b;
}
cin>>n;
while(n --) {
int a; double b;
cin>>a>>b;
map<int, double> res;
for(auto [x, y] : mp) {
res[x + a] = y * b;
}
for(auto [x, y] : res) ans[x] += y;
}
vector<pair<int, double>> v;
for(auto [x, y] : ans) {
if(y != 0)
v.push_back({x, y});
}
printf("%d", v.size());
for(int i = v.size() - 1; i >= 0; i --) {
printf(" %d %.1lf", v[i].first, v[i].second);
}
}
1010 Radix
给出n1, n2, tag和radix,tag为1表示n1为radix进制,tag为2表示n2为radix进制,另一个数进制未知。问是否有一个尽可能小的答案使n1和n2在十进制下相等。
思路:方便起见,如果tag为2,交换n1,n2,使确定的数为n1, 不确定的数为n2。
a数组是n2从高到低的每个数位,base是我们要求的进制位。由于题目设置了每个数位的数最大是35,可以看出如果答案很大的话,后面的项和第一项相差巨大,这时候暴力枚举一定会超时,但是我们这时可以大概求出l最小的取值,然后再往右枚举几位就能判断出是否会相等。把n1转化成10进制数后除以a1,再取(n-1)的根,大概是l最小的范围。如果答案比较小的话,暴力枚举。
string s1, s2;
int tag, radix;
void solve() {
cin>>s1>>s2>>tag>>radix;
reverse(s1.begin(), s1.end());
reverse(s2.begin(), s2.end());
if(tag == 2) {string s = s1; s1 = s2; s2 = s;}
ll n1 = 0;
ll base = 1;
for(int i = 0; i < s1.size(); i ++) {
int num;
if(islower(s1[i])) num = s1[i] - 'a' + 10;
else num = s1[i] - '0';
n1 += 1ll * base * num;
base *= radix;
}
ll n2 = 0;
int l = 0;
for(char ch : s2) {
int num;
if(islower(ch)) num = ch - 'a' + 10;
else num = ch - '0';
l = max(num, l);
}
l ++;
int n = s2.size();
int w;
if(islower(s2[n - 1])) w = s2[n - 1] - 'a' + 10;
else w = s2[n - 1] - '0';
int l1 = n1 / w;
if(n > 1) {
l1 = pow(l1, 1.0 / (n - 1));
if(l1 - l > 1000) l = l1;
}
while(n2 < n1) {
n2 = 0;
base = 1;
for(char ch : s2) {
int num;
if(islower(ch)) num = ch - 'a' + 10;
else num = ch - '0';
n2 += 1ll * base * num;
base *= l;
}
l ++;
}
if(n1 == n2) cout<<l - 1;
else cout<<"Impossible";
}
1011 World Cup Betting
找到三个最大的数然后做运算。
double x[3];
double ans = 1.0;
void solve() {
for(int i = 0; i < 3; i ++) {
double mx = 0.0;
for(int j = 0; j < 3; j ++) {
cin>>x[j];
mx = max(mx, x[j]);
}
if(mx == x[0]) cout<<"W ";
else if(mx == x[1]) cout<<"T ";
else cout<<"L ";
ans *= mx;
}
ans *= 0.65;
ans -= 1.0;
ans *= 2.0;
printf("%.2lf", ans);
}
1012 The Best Rank
询问学生四项成绩最好的一个排名是多少。
struct node {
string id;
int c, m, e, a;
};
int n, m;
void solve() {
vector<node> v;
cin>>n>>m;
string s;
int C, M, E, A;
for(int i = 0; i < n; i ++) {
cin>>s>>C>>M>>E;
A = (C + M + E) / 3;
v.push_back({s, C, M, E, A});
}
map<string, int> res;
map<string, char> ans;
sort(v.begin(), v.end(), [&](node a, node b) { return a.a > b.a;});
int pre = -1, idx = 0;
for(int i = 0; i < n; i ++) {
if(pre != v[i].a) idx = i;
res[v[i].id] = idx;
ans[v[i].id] = 'A';
pre = v[i].a;
}
pre = -1, idx = 0;
sort(v.begin(), v.end(), [&](node a, node b) { return a.c > b.c;});
for(int i = 0; i < n; i ++) {
if(pre != v[i].c) idx = i;
if(idx < res[v[i].id]) {
res[v[i].id] = idx;
ans[v[i].id] = 'C';
}
pre = v[i].c;
}
pre = -1, idx = 0;
sort(v.begin(), v.end(), [&](node a, node b) { return a.m > b.m;});
for(int i = 0; i < n; i ++) {
if(pre != v[i].m) idx = i;
if(idx < res[v[i].id]) {
res[v[i].id] = idx;
ans[v[i].id] = 'M';
}
pre = v[i].m;
}
pre = -1, idx = 0;
sort(v.begin(), v.end(), [&](node a, node b) { return a.e > b.e;});
for(int i = 0; i < n; i ++) {
if(pre != v[i].e) idx = i;
if(idx < res[v[i].id]) {
res[v[i].id] = idx;
ans[v[i].id] = 'E';
}
pre = v[i].e;
}
while(m --) {
string s1;
cin>>s1;
if(res.count(s1))
cout<<res[s1] + 1<<' '<<ans[s1]<<endl;
else cout<<"N/A"<<endl;
}
}
1013 Battle Over Cities
有一个无向图,问删掉一个点和它所连的边后,至少加多少条边能让图联通。
(n很小,直接暴力了) 每次新建一个并查集找有多少个连通块。
int n, m, k;
int p[N];
int find(int u) {
if(u != p[u]) p[u] = find(p[u]);
return p[u];
}
void solve() {
cin>>n>>m>>k;
vector<PII> v;
for(int i = 1; i <= m; i ++) {
int x, y;
cin>>x>>y;
v.push_back({x, y});
}
while(k --) {
int x;
cin>>x;
for(int i = 1; i <= n; i ++) p[i] = i;
for(auto [y, z] : v){
if(y == x || z == x) continue;
int px = find(y), py = find(z);
if(px != py) {
p[px] = py;
}
}
map<int, bool> mp;
for(int i = 1; i <= n; i ++) {
if(i == x) continue;
mp[find(i)] = 1;
}
cout<<mp.size() - 1<<endl;
}
}
1014 Waiting in Line
模拟排队,询问每个人的结束时间。需要注意开始时间要小于17:00, 结束时间要小于18:00.
int n, m, k, q;
void solve() {
cin>>n>>m>>k>>q;
queue<int> line[n + 1];
int idx = 1;
int t[k + 1];
for(int i = 1; i <= k; i ++) cin>>t[i];
for(int j = 1; j <= m; j ++) {
for(int i = 1; i <= n; i ++) {
if(idx > k) break;
line[i].push(idx ++);
}
if(idx > k) break;
}
int cnt = 0;
int last[n + 1];
for(int i = 1; i <= n; i ++) {
if(!line[i].size()) last[i] = -1;
int j = line[i].front();
last[i] = t[j];
}
int ans[k + 1];
while(cnt < k) {
int mn = -1;
for(int i = 1; i <= n; i ++) {
if(last[i] == -1) continue;
if(last[mn] > last[i] || mn == -1) mn = i;
}
int j = line[mn].front();
ans[j] = last[mn];
line[mn].pop();
cnt ++;
if(idx <= k) line[mn].push(idx ++);
if(line[mn].size()) last[mn] += t[line[mn].front()];
else last[mn] = -1;
}
while(q --) {
int x; cin>>x;
if(ans[x] - t[x] >= 540 || ans[x] >= 600) printf("Sorry\n");
else printf("%02d:%02d\n", 8 + ans[x] / 60, ans[x] % 60);
}
}
1015 Reversible Primes
询问一个数和他的对应的反转数是否都为质数。
int n, radix;
int pri[N], c;
bool vis[N];
void oula() {
vis[0] = vis[1] = 1;
for(int i = 2; i < N; i ++) {
if(!vis[i]) pri[c ++] = i;
for(int j = 0; i * pri[j] < N; j ++) {
vis[i * pri[j]] = 1;
if(i % pri[j] == 0) break;
}
}
}
void solve() {
cin>>radix;
string s;
int m = n;
while(m) {
int t = m % radix;
s += ('0' + t);
m /= radix;
}
reverse(s.begin(), s.end());
int base = 1;
for(int i = 0; i < s.size(); i ++) {
int t = (s[i] - '0') * base;
base *= radix;
m += t;
}
if(!vis[n] && !vis[m]) cout<<"Yes"<<endl;
else cout<<"No"<<endl;
}