当前位置: 首页 > news >正文

2025ICPC陕西省赛题解

L. easy

每行选能选的最小的两个,注意处理奇数的情况。

#include <bits/stdc++.h>
#define x first
#define y second
#define int long longusing namespace std;
typedef unsigned long long ULL ;
typedef pair<int,int> PII ;
typedef pair<long double,long double> PDD ;
const int N = 200010 , M = N * 2 , mod = 998244353 ;
int n ;
int a[1010][1010] ;void solve()
{cin >> n ;int c = 1 ;for(int i = 1 ; i <= n ; i ++)for(int j = 1 ; j <= n ; j ++)a[i][j] = c ++ ;int res = 0 ;for(int i = 1 ; i <= n ; i ++) {int u = (i + 1) / 2 ;u = 2 * (u - 1) + 1 ;res += a[i][u] + a[i][u + 1] ;}if(n % 2) res += n * n ;cout << res << "\n" ;
}
signed main()
{std::ios::sync_with_stdio(false) , cin.tie(0) , cout.tie(0) ;int t = 1 ;
//    cin >> t ;while (t --) solve() ;return 0;
}
C. gcd

其实这道题就是在问,能不能找到b的一个因数,并且不是a的因数,我们每次用b除以a,b的最大公因数即可。

#include <bits/stdc++.h>
#define x first
#define y second
#define int long longusing namespace std;
typedef unsigned long long ULL ;
typedef pair<int,int> PII ;
typedef pair<long double,long double> PDD ;
const int N = 200010 , M = N * 2 , mod = 998244353 ;void solve()
{int a , b ;cin >> a >> b ;if(a == b || b == 1) cout << "-1\n" ;else {int d = gcd(a , b) ;if(d == 1) {cout << b << "\n" ;return;}int u = b ;while (u % d == 0) {u /= d ;d = gcd(a , u) ;if(d == 1) break;}if(gcd(a , u) == 1 && gcd(b , u) != 1) cout << u << "\n" ;else cout << "-1\n" ;}
}
signed main()
{std::ios::sync_with_stdio(false) , cin.tie(0) , cout.tie(0) ;int t = 1 ;cin >> t ;while (t --) solve() ;return 0;
}
G. student

题意就是说一个人如果两边分别有大于等于和小于等于他分数的人就可以出队。
假设a[mx]是最大值的位置,a[mn]是最小值的位置,那么(mx,mn)中的人一定可以全部走掉,(1,mx)之间大于大于a[1]的一定可以走掉,(1,mn)之间小于等于a[1]的一定可以走掉,(mx,n)之间大于等于a[n]的一定可以走掉,(mn,n)之间小于等于a[n]的一定可以走掉。
也就是说我们只用考虑1,mn,mx,n,这四个位置即可,如果有最大值和最小值和两个端点重复的就又会少留下一个。注意特判n=1的情况。

#include <bits/stdc++.h>
#define x first
#define y second
#define int long longusing namespace std;
typedef unsigned long long ULL ;
typedef pair<int,int> PII ;
typedef pair<long double,long double> PDD ;
const int N = 200010 , M = N * 2 , mod = 998244353 ;
int n ;
int a[N] ;void solve()
{cin >> n ;for(int i = 1 ; i <= n ; i ++)cin >> a[i] ;if(n <= 2) {cout << n << "\n" ;return;}int res = 4 ;int mx = 0 , mn = 1e9 ;for(int i = 1 ; i <= n ; i ++)mx = max(mx , a[i]) , mn = min(mn , a[i]) ;if(mx == a[1] || mx == a[n]) res -- ;if(mn == a[1] || mn == a[n]) res -- ;cout << res << "\n" ;
}
signed main()
{std::ios::sync_with_stdio(false) , cin.tie(0) , cout.tie(0) ;int t = 1 ;
//    cin >> t ;while (t --) solve() ;return 0;
}
J. Win

贪心,依次找出需要补充1个、2个、3个字母的数量。

#include <bits/stdc++.h>
#define x first
#define y second
#define int long longusing namespace std;
typedef unsigned long long ULL ;
typedef pair<int,int> PII ;
typedef pair<long double,long double> PDD ;
const int N = 200010 , M = N * 2 , mod = 998244353 ;
int k ;
string s ;void solve()
{cin >> k >> s ;int res = 0 ;map<int,int> mp ;for(int i = 0 ; i < s.size() ; i ++) {string t = "" ;if(i + 3 < s.size()) {t = s.substr(i , 4) ;if(t == "lose") {mp[4] ++ ;i += 3 ;continue;}}if(i + 2 < s.size()) {t = s.substr(i , 3) ;if(t == "los" || t == "ose" || t == "lse" || t == "loe") {mp[3] ++ ;i += 2 ;continue;}}if(i + 1 < s.size()) {t = s.substr(i , 2) ;if(t == "lo" || t == "os" || t == "se" || t == "ls" || t == "le" || t == "oe") {mp[2] ++ ;i += 1 ;continue;}}if(s[i] == 'l' || s[i] == 'o' || s[i] == 's' || s[i] == 'e') {mp[1] ++ ;}}res = mp[4] ;for(int i = 3 ; i >= 1 ; i --) {int u = min(mp[i] , k / (4 - i)) ;res += u ;k -= (4 - i) * u ;}res += k / 4 ;cout << res << "\n" ;
}
signed main()
{std::ios::sync_with_stdio(false) , cin.tie(0) , cout.tie(0) ;int t = 1 ;
//    cin >> t ;while (t --) solve() ;return 0;
}
A. Color

贪心题。我们可以假设对于每一种我们直接w[i]+n,把全部涂成一个颜色。这是发现如果对于连续的一段长度大于w[i]的全为颜色i的段,不涂色就好,也就是代价减少(这一段长度与w[i]的差值)。注意如果开头和结尾就是颜色i这一段可以不涂。

#include <bits/stdc++.h>
#define x first
#define y second
#define int long longusing namespace std;
typedef unsigned long long ULL ;
typedef pair<int,int> PII ;
typedef pair<long double,long double> PDD ;
const int N = 200010 , M = N * 2 , mod = 998244353 ;
int n ;
int a[N] , b[N] ;void solve()
{cin >> n ;for(int i = 1 ; i <= n ; i ++) cin >> a[i] ;for(int i = 1 ; i <= n ; i ++) cin >> b[i] ;vector<int> p[n + 3] ;int u = 1 ;for(int i = 2 ; i <= n ; i ++)if(a[i] == a[i - 1]) u ++ ;else {p[a[i - 1]].push_back(u) ;u = 1 ;}p[a[n]].push_back(u) ;for(int i = 1 ; i <= n ; i ++) {int l = 1 , r = n ;while (a[l] == i) l ++ ;while (a[r] == i) r -- ;int sum = b[i] + r - l + 1 ;if(p[i].size()) {sort(p[i].begin() , p[i].end()) ;for(int j = p[i].size() - 1 ; j >= 0 ; j --) {if(p[i][j] > b[i]) sum -= p[i][j] - b[i] ;else break;}}cout << sum << " " ;}cout << "\n" ;
}
signed main()
{std::ios::sync_with_stdio(false) , cin.tie(0) , cout.tie(0) ;int t = 1 ;
//    cin >> t ;while (t --) solve() ;return 0;
}
K. Welfare

贪心思维题,很多种情况,需要考虑的比较多。
可以看代码理解,这里提供两个容易错的样例。
4 1 7 2答案是15,3 2 10 2答案是16

#include <bits/stdc++.h>
#define x first
#define y second
#define int long longusing namespace std;
typedef unsigned long long ULL ;
typedef pair<int,int> PII ;
typedef pair<long double,long double> PDD ;
const int N = 200010 , M = N * 2 , mod = 998244353 ;
int n , m , x , y ;void solve()
{cin >> n >> m >> x >> y ;if(n == 0 && m == 0) {cout << "0\n" ;return;}if(y == 0) {cout << x << "\n" ;return;}if(x == 0) {cout << (n + m) * y << "\n" ;return;}if(n > 0) {if(m == 0) {if(x > y) cout << x + (n - 1) * y << "\n" ;else cout << n * y << "\n" ;return;}if(x <= y) cout << y * (n + m) << "\n" ;else {if((n + 1) * y < x) cout << x + n * y << "\n" ;else {int l = 1 , r = n ;while (l < r) {int mid = (l + r) / 2 ;if(mid * y >= x) r = mid ;else l = mid + 1 ;}if(l * y >= x) l -- ;cout << max(x + n * y , x + (n + m - l) * y) << "\n" ;}}}else {if(x > y) cout << x << "\n" ;else cout << y * m << "\n" ;}
}
signed main()
{std::ios::sync_with_stdio(false) , cin.tie(0) , cout.tie(0) ;int t = 1 ;cin >> t ;while (t --) solve() ;return 0;
}

该下班了,剩下的明天再补。


D Stock

当看到 n ≤ 30 n \leq 30 n30时就可以想到这道题需要dfs来做了。不管对于加法还是乘法,优先处理大数才能获得最优解法,所以先排序再dfs即可。(ps:一开始用long double 一直tle换成double就ac了)。

#include <bits/stdc++.h>
#define x first
#define y second
#define int long long
//#define double long doubleusing namespace std;
typedef unsigned long long ULL ;
typedef pair<int,int> PII ;
typedef pair<double,double> PDD ;
const int N = 200010 , M = N * 2 , mod = 998244353 ;
int n ;
double u , res ;
vector<double> a , b ;void dfs(int i , int j , double x , double sum) {if(i == a.size() && j == b.size()) {res = max(res , sum) ;return;}if(i < a.size()) dfs(i + 1 , j , x + a[i] , sum + x + a[i]) ;if(j < b.size()) dfs(i , j + 1 , x * b[j] , sum + x * b[j]) ;
}
void solve()
{cin >> n >> u ;for(int i = 0 ; i < n ; i ++) {char c ;double x ;cin >> c >> x ;if(c == '+') a.push_back(x) ;else b.push_back(x) ;}sort(a.begin() , a.end()) , sort(b.begin() , b.end()) ;reverse(a.begin() , a.end()) , reverse(b.begin() , b.end()) ;dfs(0 , 0 , u , 0) ;res = res / (double)(n * 1.0) ;cout << fixed << setprecision(12) << res << "\n";
}
signed main()
{std::ios::sync_with_stdio(false) , cin.tie(0) , cout.tie(0) ;int t = 1 ;
//    cin >> t ;while (t --) solve() ;return 0;
}

相关文章:

  • MySQL 学习(十)执行一条查询语句的内部执行过程、MySQL分层
  • 【SPIN】PROMELA语言编程入门基础语法(SPIN学习系列--1)
  • 在自动化脚本中使用找色实现精确定位目标区域
  • GPU八卡A100使用INT4-W4A16量化大模型实验
  • 电路中零极点的含义
  • AcroForm 文档(打开时)级脚本对比 Excel VBA 参考
  • worldquant rank函数
  • 多智能体Multi-Agent应用实战与原理分析
  • 单片机-STM32部分:16、Git工具使用
  • 理解c++中关键字友元friend的作用
  • 使用nps配置内网穿透加域名解析
  • C++二项式定理:原理、实现与应用
  • nvidia-smi-Failed to initialize NVML: Driver/library version mismatch
  • Newton 迭代
  • Openlayers:如何注册一个新的坐标系统
  • 【数字图像处理】半开卷复习提纲
  • 建筑迈向绿色发展之路,楼宇自控成建筑可持续发展关键技术
  • 室内定位:热门研究方向与未解难题深度解析
  • 培训机构教务管理系统软件的功能有哪些?
  • 【c语言】动态内存分配
  • 对谈|“大礼议”:嘉靖皇帝的礼法困境与权力博弈
  • 国家卫生健康委通报关于肖某引发舆情事件调查处置进展情况
  • 《大风杀》导演张琪:为了不算计观众,拍了部不讨好的警匪片
  • 透视社会组织创新实践中的花开岭现象:与乡村发展的融合共进
  • 阿尔巴尼亚执政党连续第四次赢得议会选举,反对党此前雇用特朗普竞选经理
  • 联合国秘书长欢迎中美经贸高层会谈成果