2024天梯赛
读题仔细点吧,背景还是可以看一下的
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define endl "\n"
#define inf 0x3f3f3f3f
void solve(){
int a,b;
cin >> a >> b;
//第一行只输出提示(红灯输出"biii" 绿灯输出"dudu") or 不提示(-)
if(b || a == 2){
cout << "-";
}else{
if(a == 1) cout << "dudu";
else cout << "biii";
}
cout << endl;
//第二行只输出行不行动 绿灯行 红灯黄灯停
if(a == 1) cout << "move";
else cout << "stop";
}
signed main(){
ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
int _ = 1;
//cin >> _;
while(_--) solve();
return 0;
}
题意:给定全班总人数为 \(n\),其中有 \(m\) 项技能,分别有 \(k1、k2、……、k_m\) 个人会,问至少有多少人$ m$ 项都会。
前面那题给晃了一下,这题脑子都不转了。
思路:假设技能点总数为\(sum\),假设每个人都会\(m-1\)项,则剩下\(sum-(m-1) \times n\)个技能点,一定是属于四项全能的人的。注意最小人数为\(0\)。
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define endl "\n"
#define inf 0x3f3f3f3f
int n, m;
int sum;
void solve(){
cin >> n >> m;
for(int i = 1; i <= m ; i ++){
int x; cin >> x;
sum += x;
}
cout << max((int)0,sum - n*(m-1));
}
signed main(){
ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
int _ = 1;
//cin >> _;
while(_--) solve();
return 0;
}
题意:给\(n\)个违禁词和一个字符串,问字符串中的违禁词是否小于\(k\),如果是,则将违禁词替换成\(<censored>\)后输出,否则输出\(He \ Xie\ Ni \ Quan\ Jia!\)
注意:
1.getline读入字符串之前,如果前面有输入,一定要把'\n'给getchar()了(如果多行getline不用)
2.待检查字符串可能出现\(<censored>\),\(@\),\(!\)等等符号,所以要找一个在数据中待见字符串没有出现过的才能通过,所以只能一个个换着试,不得不说,题目和数据都真ex。
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define endl "\n"
#define inf 0x3f3f3f3f
int n, m;
string s[110];
string res;
int cnt;
void solve(){
cin >> n;
for(int i = 0 ; i < n ; i ++) cin >> s[i];
cin >> m; getchar();
getline(cin,res);
//cout << res << endl;
for(int i = 0 ; i < n ; i ++){
int pos = res.find(s[i]);
//cout << res << " " << s[i] << " " << pos << endl;
while(pos != -1){
cnt ++;
res = res.substr(0,pos) + "@!@#!" + res.substr(pos+s[i].size());
pos = res.find(s[i]);
}
}
if(cnt >= m){
cout << cnt << endl;
cout << "He Xie Ni Quan Jia!";
}else{
int pos = res.find("@!@#!");
while(pos != -1){
res = res.substr(0,pos) + "<censored>" + res.substr(pos+5);
pos = res.find("@!@#!");
}
cout << res;
}
}
signed main(){
//ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
int _ = 1;
//cin >> _;
while(_--) solve();
return 0;
}
简单模拟
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define endl "\n"
#define inf 0x3f3f3f3f
int n;
double p[110];
int cnt[110];
double sum;
void solve(){
cin >> n;
for(int i = 1 ; i <= n ; i ++) cin >> p[i];
int x, y;
cin >> x >> y;
while(x != 0){
sum += (double)y * p[x];
cnt[x] += y;
cin >> x >> y;
}
for(int i = 1; i <= n ; i ++){
cout << cnt[i] << endl;
}
printf("%.2f\n",sum);
}
signed main(){
//ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
int _ = 1;
//cin >> _;
while(_--) solve();
return 0;
}
看清楚题意,整数连续性是指多次操作后变成个位数,而不是回到自己的数字!!!因为是乘法,所以不需要几步,就能判断一个数的连续性。
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define endl "\n"
#define inf 0x3f3f3f3f
map<int,int> mp;
int mx;
int get(int x){
if(x/10==0){
mp[x] = 0;
return 0;
}
int now = x,t,cnt = 0;
while(now/10){
t = now;
int s = 1;
while(t){
s *= t % 10;
t /= 10;
}
now = s;
cnt++;
}
mp[x] = cnt;
return cnt;
}
void solve(){
int l ,r ;
cin >> l >> r;
for(int i = l ; i <= r ; i ++){
mx = max(mx,get(i));
}
cout << mx << endl;
int f = 1;
for(auto [x,y] : mp){
if(y == mx)
{
if(f) f = 0;
else cout << " ";
cout << x;
}
}
}
signed main(){
//ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
int _ = 1;
//cin >> _;
while(_--) solve();
return 0;
}
看清楚题目要求!有两个
1.每个\(3 \times 3\)的小格子里\(1-9\)只能出现一次
2.整个\(9 \times 9\)的大的里,每行每列\(1-9\)也只能出现一次
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define endl "\n"
#define inf 0x3f3f3f3f
int n;
int a[10][10];
void solve(){
int f = 1;
for(int i = 1 ; i <= 9 ; i ++)
for(int j = 1 ; j <= 9 ; j ++)
cin >> a[i][j];
for(int i = 1 ; i <= 7 ; i += 3){
for(int j = 1 ; j <= 7 ; j += 3){
vector<bool> vis(10,false);
for(int x = i ; x <= i + 2 ; x ++){
for(int y = j ; y <= j + 2 ; y ++){
if(a[x][y] >= 1 && a[x][y] <= 9) vis[a[x][y]] = true;
}
}
for(int o = 1; o <= 9 ; o ++) if(vis[o] == false) f = 0;
}
}
for(int x = 1; x <= 9 ; x ++){
vector<bool> vis(10,false);
for(int y = 1; y <= 9 ; y ++){
if(a[x][y] >= 1 && a[x][y] <= 9) vis[a[x][y]] = true;
}
for(int o = 1; o <= 9 ; o ++) if(vis[o] == false) f = 0;
}
for(int y = 1; y <= 9 ; y ++){
vector<bool> vis(10,false);
for(int x = 1; x <= 9 ; x ++){
if(a[x][y] >= 1 && a[x][y] <= 9) vis[a[x][y]] = true;
}
for(int o = 1; o <= 9 ; o ++) if(vis[o] == false) f = 0;
}
cout << f << endl;
}
signed main(){
ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
int _ = 1;
cin >> _;
while(_--) solve();
return 0;
}
赛时用\(set\)过了,但是数据水了,输入的时候就是\(O(nklogk)\),已经\(T\)了
所以考虑使用\(vector\),然后排序(如果排序,和上面一样是\(O(nklogk)\)了,而观察输入,一定是顺序的,好巧!),二分查找,复杂度\(O(Qklog(k))\)
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define endl "\n"
#define inf 0x3f3f3f3f
const int N = 1e5 + 10;
int n, m;
vector<int> v[N];
void solve(){
cin >> n >> m;
for(int i = 1 ; i <= n ; i ++){
int k; cin >> k;
for(int j = 1 ; j <= k ; j ++){
int t; cin >> t;
v[t].push_back(i);
}
}
int t; cin >> t;
while(t--){
int x, y; cin >> x >> y;
int cnt = 0;
for(auto it : v[x]){
int pos = lower_bound(v[y].begin(),v[y].end(),it) - v[y].begin();
if(v[y][pos]==it) cnt ++;
}
cout << cnt << endl;
}
}
signed main(){
ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
int _ = 1;
//cin >> _;
while(_--) solve();
return 0;
}
用缩写映射到每个缩写对应的话就可以
坑点:
1.取缩写的时候,第一个字符可能是空格,每个单词之间的空格可能不为1
2.翻译的话里面可能有重复的都要并列输出出来
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define endl "\n"
#define inf 0x3f3f3f3f
const int N = 2e5 + 10;
int n;
map<string,multiset<string>> mp;
string get(string s){
int len = s.size();
string res = "";
for(int i = 0 ; i < len ; i ++){
while(s[i] == ' ' && i < len) i++;
res += s[i];
while(s[i] != ' ' && i < len) i++;
}
return res;
}
void solve(){
cin >> n; getchar();
string s, t;
for(int i = 1 ; i <= n ; i ++){
getline(cin,s); t = get(s);
mp[t].insert(s);
}
int q; cin >> q; getchar();
for(int i = 1 ; i <= q; i ++){
getline(cin,s); t = get(s);
if(mp.count(t))
{
int first = 1;
for(auto it : mp[t]){
if(first) first = 0;
else cout << "|";
cout << it;
}
}else{
cout << s;
}
cout << endl;
}
}
signed main(){
//ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
int _ = 1;
//cin >> _;
while(_--) solve();
return 0;
}
数据结构简单题
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define endl "\n"
#define inf 0x3f3f3f3f
const int N = 1e5 + 10;
int n, root, k;
vector<int> e[N],ans;
int f = 1;
void dfs(int r){
ans.push_back(r);
if(e[r].size() == 0) return;
if(f && (int)e[r].size() != k) f = 0;
k = max((int)e[r].size(),k);
for(auto v : e[r]){
dfs(v);
}
}
void solve(){
cin >> n;
int x;
for(int i = 1 ; i <= n ; i ++){
cin >> x;
if(x == 0) root = i;
else e[x].push_back(i);
}
k = e[root].size();
dfs(root);
cout << k << " " << (f?"yes":"no") << endl;
int fir = 1;
for(auto it : ans){
if(fir) fir = 0;
else cout << " ";
cout << it ;
}
}
signed main(){
ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
int _ = 1;
//cin >> _;
while(_--) solve();
return 0;
}
其实赛时思路一样,但是没想清楚怎么写,最后半个小时都没写对,这个时候就该果断放弃写L3-1的,唉,差一点点,还是太菜了
思路:爆搜,注意剪枝
1.一个\(n\times n\)大小的矩阵,只用枚举 \((n-1) \times (n-1)\) 大小的矩阵即可
2.枚举每一个数的时候,需要考虑前面的和,只需要枚举到\(k-sum\)
3.所以只需要记录当前每行,每一列的和即可,方便了2,最后也方便1的检查,即查看最右下角需要填的数是否在\(0-l\)之间
#include <bits/stdc++.h>
using namespace std;
#define endl "\n"
//#define int long long
int row[5],col[5];
int k, n;
int cnt;
void dfs(int x,int y){
if(y == n){
x ++; y = 1;
}
if(x == n){
int sumr = 0 , sumc = 0;
for(int i = 1 ; i <= n - 1 ; i ++) sumr += (k - row[i]);
for(int i = 1 ; i <= n - 1 ; i ++) sumc += (k - col[i]);
//实际上sumr和sumc相同,都是左上角(n-1)*(n-1)个数字之和
//所以不用计算最右小角的数是否合法 右下角的数字一定是(k - sumr/sumc) >= 0 就ok
if(sumr <= k && sumc <= k) cnt++;
return ;
}
for(int i = 0 ; i <= k - row[x] && i <= k - col[y] ; i ++){//剪枝
row[x] += i, col[y] += i;
dfs(x , y + 1);
row[x] -= i, col[y] -= i;
}
}
void solve()
{
cin >> k >> n;
dfs(1, 1);
cout << cnt;
}
signed main()
{
//ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
int _;
//cin >> _;
_ = 1;
while(_--) solve();
return 0;
}
从大本营出发,一遍BFS就可以算出每个点到大本营的最短路,然后判断就可以
有趣的是我把判断大本营那段代码写成了==0,居然过了两个样例还过了前三个测试点,简直了,还让我找了半天的错。
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define endl "\n"
#define inf 0x3f3f3f3f
const int N = 1e5 + 10;
int n, m, x, y;
int g[110][110];
int dis[110][110];
int dx[]={0,0,-1,1};
int dy[]={1,-1,0,0};
map<int,int> cnt,ans;
void bfs(int x,int y){
queue<pair<int,int> > q;
q.push({x,y});
dis[y][x] = 1;
while(q.size()){
auto [x,y] = q.front() ; q.pop();
for(int i = 0 ; i < 4 ; i ++){
int nx = x + dx[i], ny = y + dy[i];
if(nx > n || nx < 1 || ny > m || ny < 1) continue;
if(g[nx][ny] == 0) continue;
if(!dis[nx][ny]||dis[nx][ny] > dis[x][y] + 1){
dis[nx][ny] = dis[x][y] + 1;
q.push({nx,ny});
}
}
}
}
void solve(){
cin >> n >> m;
for(int i = 1; i <= n ; i ++)
for(int j = 1; j <= m ; j ++){
cin >> g[i][j];
if(g[i][j] == 2) x = i , y = j;
}
bfs(x,y);
int q, o, p;
cin >> q;
for(int i = 1 ; i <= q ; i ++){
cin >> o >> p;
if(dis[p][o] == 0 || dis[p][o] == 1) continue;
int path = dis[p][o];
cnt[path] ++;
//cout << i << " " << path << endl;
ans[i] = path;
}
int mn = LONG_LONG_MAX,res;
for(auto [x,y] : ans){
if(cnt[y] == 1 && mn > y){
res = x;
mn = y;
}
}
if(mn != LONG_LONG_MAX)cout << res << " " << mn;
else cout << "No winner.";
}
signed main(){
ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
int _ = 1;
//cin >> _;
while(_--) solve();
return 0;
}