2020 ICPC 上海(部分题解)

Posted jojoqiao

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2020 ICPC 上海(部分题解)相关的知识,希望对你有一定的参考价值。

@

目录

G

(签到 思维题)
题目大意: 求斐波那契数列中 i : 1~n , j : i+1~n 中 fi*fj 为偶数的个数
思路:两数相乘为偶数 则一个数为偶数即可 斐波那契数列中3的倍数为偶数 则只需要求n中为3的倍数的个数 计算匹配数减去重复匹配的数量即可
代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e6 + 10;
int main()

	ll n;cin>>n;
	ll k=n/3;
	ll ans = k*(n-1) - ((k-1)*k/2);
	cout<<ans<<endl;

M

题目大意:给出n个文件的路径,你需要删除的,再给出m个文件的路径,你不能删除的,如果一个文件夹中的所有文件都可以删除那么就一次性删除即可,问最少删除次数
思路:map 存一下字符串 ,先处理文件标记首先为0,如果不可以删除标记为1,对于已标记为0的字符串,将其标记为2,如果后面再次出现那么整个路径都需要删除 则ans--
代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int t, n, m;
int main()

	cin >> t;
	while (t--)
	
		cin >> n >> m;
		int ans = n;
		map<string, int> mp;
		string s, ss[105];
		for (int i = 1; i <= n + m; i++)
		
			cin >> ss[i];
			s.clear();
			for (int j = 0; j < ss[i].size(); j++)
			
				if (ss[i][j] == \'/\')
				
					if (i > n) mp[s] = 1; //前n个文件需要删除 后面不能删除
					else mp[s] = 0;//所有m路径记为1 其他均为0
				
				else s += ss[i][j];
			
		
		for (int i = 1; i <= n; i++)
		
			s.clear();
			for (int j = 0; j < ss[i].size(); j++)
			
				if (ss[i][j] == \'/\')
				
					if (mp[s] == 0) mp[s] = 2;//说明可以删去 先标记为2 后面出现再减
					else if (mp[s] == 1) continue;//不能删去
					else //标记为2 需要删去
					
						ans--;
						break;
					
				
				else s += ss[i][j];
			
		
		cout << ans << endl;
	

B

题目大意:扫雷,一个n×m的矩阵,X代表雷,.代表没有雷。X的权值为0,.的点权值为相邻雷(X)的数目,一个图的权值为所有权值相加。
现在给你两个图A和图B,求得不超过nm/2次数修改B(.->X 或则X->.)使得sum与A得相同。(否则输出-1)。
思路:可知A图所有的X变为.,.变为X,图的权值不变,所以如果A跟B中不同元素个数大于n
m/2,则直接将A图变成相反的即可,且题目一定有解。
代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e3 + 10;
string a[N], b[N];
int main()

    int n, m, cnt = 0;
    cin >> n >> m;
    for (int i = 0; i < n; i++)
        cin >> a[i];
    for (int i = 0; i < n; i++)
        cin >> b[i];
    for (int i = 0; i < n; i++)
        for (int j = 0; j < m; j++)
            if (a[i][j] != b[i][j]) cnt++;
    if (cnt > (n * m / 2))
    
        for (int i = 0; i < n; i++)
            for (int j = 0; j < m; j++)
            
                if (a[i][j] == \'.\') a[i][j] = \'X\';
                else a[i][j] = \'.\';
            
    
    for (int i = 0; i < n; i++)
        cout << a[i] << endl;

D

题目大意:有一个数轴,范围为[ 0 ,n ],数轴上有两个人,位置和速度为p1,v1,p2,v2,求出两人路程覆盖数轴的最小时间。
思路:分类讨论:
三种情况:(假设p1完全在p2的左边,p1<p2)

  1. p1,p2相向而行
  2. p1单独走全程,或者p2单独走全程
  3. p1,p2相背而行,(需要二分找到中间相遇点,由分析可知相遇点一定在p1,p2之间)
    代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e3 + 10;
int t;
double n, p1, p2, v1, v2, ans;
bool check(double mid)

    double t1 = min(mid - p1 + mid, mid + p1) / v1;
    double t2 = min(p2 - mid + n - mid, n - p2 + n - mid) / v2;
    ans = min(ans, max(t1, t2));
    return t1 < t2;

int main()

    cin >> t;
    while (t--)
    
        cin >> n >> p1 >> v1 >> p2 >> v2;
        if (p1 > p2)
            swap(p1, p2), swap(v1, v2);
        ans = 1e9 + 10;
        //情况1
        ans = min(ans, max((n - p1) / v1, p2 / v2));
        //情况2
        ans = min(ans, min(p1 + n, n - p1 + n) / v1);
        ans = min(ans, min(p2 + n, n - p2 + n) / v2);
        //情况3
        double l = p1, r = p2;
        while (r - l > 1e-11)
        
            double mid = (l + r) / 2;
            if (check(mid))
                l = mid;
            else
                r = mid;
        
        printf("%.10f\\n", ans);
    

I

题目大意:有n个共圆心的圆,半径相差为1,有m条线通过圆心将这n个圆平分,求所有交点的距离和。
思路:1.圆心点到所有点的距离和(m条直径和),如果m为1,则不用考虑。
2.每一层的点之间的距离,(两点之间考虑是弧长近,还是走两个半径近),加上对称点的距离。
3.每层之间各点距离和。
代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e3 + 10;
const double PI = acos(-1);
double p[N], cir[N];
int main()

    int n, m;
    cin >> n >> m;
    double ans = 0, h = PI / m;
    if (m > 1)
        ans += n * (n + 1) * m;//圆心到每个点的距离
    for (int i = 1; i <= n; i++)
    
        for (int j = 1; j < m; j++)
        
            p[i] += min(2.0 * i, j * i * h);//对于一个点计算一边两点之间的距离
        
        p[i] *= 2.0;//添加另一边
        p[i] += 2.0 * i;//加上对称点
        ans += p[i] * m;//算上整个层的距离
        ans += (cir[i - 1] + (i - 1) * 2 * m) * 2 * m;//计算本层圆到下层圆的和
        cir[i] = cir[i - 1] + (i - 1) * 2 * m + p[i];//前缀和
    
    printf("%.10f\\n", ans);

以上是关于2020 ICPC 上海(部分题解)的主要内容,如果未能解决你的问题,请参考以下文章

2021 ICPC 南京站+上海站 部分题解

ICPC2019上海区域赛 部分题解(正在更新)

2019-2020 ICPC, NERC, Southern and Volga Russian Regional Contest 部分题目题解

2020 icpc 上海站+模拟+dp

2020 icpc 上海站+模拟+dp

第45届ICPC沈阳站部分题解(DFGHIK)