2025“钉耙编程”中国大学生算法设计春季联赛(1)题解(会做的做完了)

1001

签到

#include <bits/stdc++.h>

using namespace std;

//#define int long long
#define endl '\n' 
using u32 = unsigned;
using i64 = long long;
using u64 = unsigned long long;
using PII = pair<int,int>; 

const int N=1e5+5;

void solve() {
	int n;
	cin >> n;
	string t,s;
	cin>>t;
	bool f=0;
	for(int i=1;i<=n;i++){
		cin>>s;
		if(s==t){cout<<i<<endl;f=1;}
	
	}
	if(!f){
		cout<<-1<<endl;
	}
}

signed main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	
	int t;
	cin >> t;
	
	while (t--) {
		solve();
	}
	
	return 0;
}


/*
*                        _oo0oo_
*                       o8888888o
*                       88" . "88
*                       (| -_- |)
*                       0\  =  /0
*                     ___/`---'\___
*                   .' \\|     |// '.
*                  / \\|||  :  |||// \
*                 / _||||| -:- |||||- \
*                |   | \\\  - /// |   |
*                | \_|  ''\---/''  |_/ |
*                \  .-\__  '-'  ___/-. /
*              ___'. .'  /--.--\  `. .'___
*           ."" '<  `.___\_<|>_/___.' >' "".
*          | | :  `- \`.;`\ _ /`;.`/ - ` : | |
*          \  \ `_.   \_ __\ /__ _/   .-` /  /
*      =====`-.____`.___ \_____/___.-`___.-'=====
*                        `=---='
* 
* 
*      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* 
*            佛祖保佑       永不宕机     永无BUG
*/

1002

船长

 相邻的两个人pk,获胜的进入下一轮,直到剩一个人,我们要成为胜利者。

n个人有k个威胁者,他们身上的概率初始为f=1,进入下一轮的概率为1/2,普通人的概率初始为0,不用算。

我们pk必胜,要求不会碰上那k个人的概率

ans=1

遇见一个ans=ans*(1-f)

那么相遇的时候他们的f都是多少呢?

假如威胁者打败威胁者,那么它俩就合成一个威胁(f1+f2)/2

假如威胁者打败普通人,那么f/2

假如轮空f不变

剩下的看注释吧,分数取模,除以a等于乘a的逆元 fastpow(a,mod-2,mod)

// Problem: 船长
// Contest: HDOJ
// URL: https://acm.hdu.edu.cn/contest/problem?cid=1150&pid=1002
// Memory Limit: 524288 MB
// Time Limit: 1000 ms
//
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>

using namespace std;

#define endl '\n'
// #define int long long
using u32 = unsigned;
using i64 = long long;
using u64 = unsigned long long;
using PII = pair<int, int>;

const int mod = 998244353, inv2 = (mod + 1) / 2;

int Power(int a, int k) {
  int res = 1;
  for (; k; k >>= 1, a = 1LL * a * a % mod)
    if (k & 1) res = 1LL * res * a % mod;
  return res;
}
// 求逆元
int Inv(int a) { return Power(a, mod - 2); }

void solve() {
  int n, k, win;
  cin >> n >> k >> win;
  win--;                // 从0开始计数
  vector<int> wei(k);   // 威胁位置
  vector<int> f(k, 1);  // 威胁的初始概率
  for (int i = 0; i < k; i++) {
    cin >> wei[i];
    wei[i]--;  // 0开始
  }
  sort(wei.begin(), wei.end());  // 编号

  int ans = 1;  // 概率,不碰上

  while (!wei.empty()) {  // 还有可能威胁
    vector<int> new_wei, new_f;

    win /= 2;  // 相当于找下一轮位置

    for (int i = 0; i < wei.size();) {
      if (win == wei[i] / 2) {  // 遇见敌人
        ans = 1ll * ans * (1 - f[i] + mod) % mod;
        i++;
      } else {
        new_wei.push_back(wei[i] / 2);
        if (i + 1 < wei.size() &&
            (wei[i] / 2) == (wei[i + 1] / 2)) {  // 两个威胁相遇
          new_f.push_back(1LL * inv2 * (f[i] + f[i + 1]) % mod);  // 相加除以2
          i += 2;  // 处理两个

        } else if ((wei[i] ^ 1) <
                   n) {  // 威胁和普通,wei[i]是偶数而且是n-1才会==n
          new_f.push_back(1LL * f[i] * inv2 % mod);  // 直接除以2
          i += 1;                                    // 一个
        } else {
          new_f.push_back(f[i]);  // 轮空
          i += 1;                 // 一个
        }
      }
    }
    wei = new_wei;
    f = new_f;
    n = (n + 1) / 2;
  }
  cout << ans << endl;
}

signed main() {
  std::ios::sync_with_stdio(false);
  std::cin.tie(nullptr);

  int t;
  cin >> t;

  while (t--) {
    solve();
  }

  return 0;
}

/*
 *                        _oo0oo_
 *                       o8888888o
 *                       88" . "88
 *                       (| -_- |)
 *                       0\  =  /0
 *                     ___/`---'\___
 *                   .' \\|     |// '.
 *                  / \\|||  :  |||// \
 *                 / _||||| -:- |||||- \
 *                |   | \\\  - /// |   |
 *                | \_|  ''\---/''  |_/ |
 *                \  .-\__  '-'  ___/-. /
 *              ___'. .'  /--.--\  `. .'___
 *           ."" '<  `.___\_<|>_/___.' >' "".
 *          | | :  `- \`.;`\ _ /`;.`/ - ` : | |
 *          \  \ `_.   \_ __\ /__ _/   .-` /  /
 *      =====`-.____`.___ \_____/___.-`___.-'=====
 *                        `=---='
 *
 *
 *      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 *
 *            佛祖保佑       永不宕机     永无BUG
 */

1003

船舱

1004

海浪

1005

航线

多加一个维度,为方向维度

先把二维坐标转为一维坐标,再跑堆优化迪杰斯特拉,dist和vis数组都加一个方向维度

bfs过程中既考虑方向最短也考虑直线最短

// Problem: 航线
// Contest: HDOJ
// URL: https://acm.hdu.edu.cn/contest/problem?cid=1150&pid=1005
// Memory Limit: 524288 MB
// Time Limit: 2000 ms
//
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>

using namespace std;

typedef long long int64;

const int N = 100000;
const int64 INF = (1LL << 60) - 1;
const int dx[4] = {0, -1, 0, 1};
const int dy[4] = {1, 0, -1, 0};

int n, m, t[N + 9], d[N + 9];

int Encode(int x, int y) { return (x - 1) * m + y; }
pair<int, int> Decode(int id) {
  return make_pair((id - 1) / m + 1, (id - 1) % m + 1);
}

void Read() {
  cin >> n >> m;
  for (int i = 1; i <= n; ++i)
    for (int j = 1; j <= m; ++j) cin >> t[Encode(i, j)];
  for (int i = 1; i <= n; ++i)
    for (int j = 1; j <= m; ++j) cin >> d[Encode(i, j)];
}

int64 dis[N + 9][4];
bool vis[N + 9][4];

void Dijkstra() {
  int st = Encode(1, 1);
  int td = Encode(n, m);
  for (int i = 1; i <= n * m; ++i)
    for (int j = 0; j < 4; ++j) {
      dis[i][j] = INF;
      vis[i][j] = 0;
    }
  priority_queue<tuple<int64, int, int>, vector<tuple<int64, int, int>>,
                 greater<tuple<int64, int, int>>>
      pq;
  dis[st][0] = t[st];
  pq.push(make_tuple(0, st, 0));
  while (!pq.empty()) {
    auto top = pq.top();
    pq.pop();
    int64 val = get<0>(top);
    int p = get<1>(top);
    int u = get<2>(top);
    if (vis[p][u]) continue;
    vis[p][u] = 1;
    for (int v = 0; v < 4; ++v) {
      if (dis[p][u] + d[p] >= dis[p][v]) continue;
      dis[p][v] = dis[p][u] + d[p];
      pq.push(make_tuple(dis[p][v], p, v));
    }
    pair<int, int> xy = Decode(p);
    int x = xy.first + dx[u];
    int y = xy.second + dy[u];
    int q = Encode(x, y);
    auto OutMap = [&](int x, int y) {
      return x < 1 || x > n || y < 1 || y > m;
    };
    if (!OutMap(x, y) && dis[p][u] + t[q] < dis[q][u]) {
      dis[q][u] = dis[p][u] + t[q];
      pq.push(make_tuple(dis[q][u], q, u));
    }
  }
  cout << dis[td][3] << '\n';
}

void work() {
  Read();
  Dijkstra();
}

int main() {
  ios::sync_with_stdio(0);
  cin.tie(0);
  int T = 1;
  cin >> T;
  while (T--) {
    work();
  }
  return 0;
}

/*
 *                        _oo0oo_
 *                       o8888888o
 *                       88" . "88
 *                       (| -_- |)
 *                       0\  =  /0
 *                     ___/`---'\___
 *                   .' \\|     |// '.
 *                  / \\|||  :  |||// \
 *                 / _||||| -:- |||||- \
 *                |   | \\\  - /// |   |
 *                | \_|  ''\---/''  |_/ |
 *                \  .-\__  '-'  ___/-. /
 *              ___'. .'  /--.--\  `. .'___
 *           ."" '<  `.___\_<|>_/___.' >' "".
 *          | | :  `- \`.;`\ _ /`;.`/ - ` : | |
 *          \  \ `_.   \_ __\ /__ _/   .-` /  /
 *      =====`-.____`.___ \_____/___.-`___.-'=====
 *                        `=---='
 *
 *
 *      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 *
 *            佛祖保佑       永不宕机     永无BUG
 */

1006

密码

 

个数用哈希表存比较好(但是map过了)

#include <bits/stdc++.h>

using namespace std;

//#define int long long
#define endl '\n' 
using u32 = unsigned;
using i64 = long long;
using u64 = unsigned long long;
using PII = pair<int,int>; 

const int N=1e5+5;

void solve() {
	int n;
	cin >> n;
	vector<int>a(3);
	map<int,int>mp;
	
	for(int i=1;i<=n;i++){
		cin>>a[0]>>a[1]>>a[2];
		sort(a.begin(),a.end());
		
		do{
			if((a[0]-a[1])%a[2]==0){
				
				if((a[0]-a[1])/a[2]>=0)
				mp[(a[0]-a[1])/a[2]]++;
			}
		}while(next_permutation(a.begin(),a.end()));
		for(auto x:mp){
			if(x.second>=n){
				cout<<x.first<<endl;
			}
		}
	}
}

signed main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	
	int t;
	cin >> t;
	
	while (t--) {
		solve();
	}
	
	return 0;
}

1007

分配宝藏

n=1我自己同意就行

n=2我还要拉拢一个船员,但是第一个船员总想杀了我,而我死后第二个船员将得到0,所以我给第二个船员1就可以

n=3 我给他们 0 1 0或者0 0 2才能获胜,所以要想船员同意,就得让他们得到的比我死后他们的分配的多

规律就是 

0

0 1

0 1 0

0 1 0 1

题目要求输出 R=(i=1∑n​i⋅ri​)mod(109+7)

// Problem: 分配宝藏
// Contest: HDOJ
// URL: https://acm.hdu.edu.cn/contest/problem?cid=1150&pid=1007
// Memory Limit: 524288 MB
// Time Limit: 1000 ms
//
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>

using namespace std;

#define endl '\n'
#define int long long
using u32 = unsigned;
using i64 = long long;
using u64 = unsigned long long;
using PII = pair<int, int>;

const int N = 1e5 + 5, mod = 1e9 + 7;

void solve() {
  int n;
  cin >> n;
  cout << n / 2 * (n / 2 + 1) % mod << endl;
}

signed main() {
  std::ios::sync_with_stdio(false);
  std::cin.tie(nullptr);

  int t;
  cin >> t;

  while (t--) {
    solve();
  }

  return 0;
}

/*
 *                        _oo0oo_
 *                       o8888888o
 *                       88" . "88
 *                       (| -_- |)
 *                       0\  =  /0
 *                     ___/`---'\___
 *                   .' \\|     |// '.
 *                  / \\|||  :  |||// \
 *                 / _||||| -:- |||||- \
 *                |   | \\\  - /// |   |
 *                | \_|  ''\---/''  |_/ |
 *                \  .-\__  '-'  ___/-. /
 *              ___'. .'  /--.--\  `. .'___
 *           ."" '<  `.___\_<|>_/___.' >' "".
 *          | | :  `- \`.;`\ _ /`;.`/ - ` : | |
 *          \  \ `_.   \_ __\ /__ _/   .-` /  /
 *      =====`-.____`.___ \_____/___.-`___.-'=====
 *                        `=---='
 *
 *
 *      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 *
 *            佛祖保佑       永不宕机     永无BUG
 */

1008

运输

1009

切割木材

// Problem: 切割木材
// Contest: HDOJ
// URL: https://acm.hdu.edu.cn/contest/problem?cid=1150&pid=1009
// Memory Limit: 524288 MB
// Time Limit: 3000 ms
//
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>

using namespace std;

#define endl '\n'
#define int long long
using u32 = unsigned;
using i64 = long long;
using u64 = unsigned long long;
using PII = pair<int, int>;

const int N = 1e5 + 5, INF = 0x3f3f3f3f3f3f3f3f;

void solve() {
  int n, m;
  cin >> n >> m;
  vector<int> a(n + 10), g((1 << m) + 10);
  for (int i = 1; i <= n; i++) {
    cin >> a[i];
  }
  for (int i = 0; i < (1 << m); i++) {
    cin >> g[i];
  }
  vector<int> dp(n + 10, -INF);  // 取max,初始取小值
  dp[0] = 0;                     // 到i的时候最大答案

	//and,or,对应值
  map<PII, int> mp;
  mp[{(1 << m) - 1, 0}] = 0;
  for (int i = 1; i <= n; i++) {
    map<PII, int> temp;

    for (auto [t, val] : mp) {
      int sand = t.first, sor = t.second;
      sand &= a[i], sor |= a[i];

      if (temp.count({sand, sor})) {
        temp[{sand, sor}] = max(val, temp[{sand, sor}]);
      } else {
        temp[{sand, sor}] = val;
      }
      dp[i] = max(dp[i], val + g[sor - sand]);
    }

    if (temp.count({(1 << m) - 1, 0})) {
      temp[{(1 << m) - 1, 0}] = max(dp[i], temp[{(1 << m) - 1, 0}]);
    } else {
      temp[{(1 << m) - 1, 0}] = dp[i];
    }

    mp = temp;
  }

  cout << dp[n] << endl;
}

signed main() {
  std::ios::sync_with_stdio(false);
  std::cin.tie(nullptr);

  int t;
  cin >> t;

  while (t--) {
    solve();
  }

  return 0;
}

1010

返航
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值