2020 ICPC Shanghai Site 2020 ICPC上海 题解

G 题目链接:Problem - G - Codeforces

 input1:

3

output1:

2

input2:

10

output2:

24

input3:

100

output3:

2739

题意:

给定一个数 n ,问斐波那契数列前 n 项任取两项,相乘等于偶数的情况有几种。

思路:

签到题。

显而易见的结论: 奇数相乘等于奇数,其他情况得到的都是偶数。

所以我们只需要用组合数解决问题。答案就是n个数任取两个的情况减去n个数中的奇数任取两个的情况。具体公式见代码。

代码如下:

#include<bits/stdc++.h>
#define endl "\n"
using namespace std;
typedef long long ll;

ll n; 
int main()
{
 	ios::sync_with_stdio(false);
  	cin.tie(0);
 	cout.tie(0);
 	cin>>n;
 	cout<<(n-1)*n/2-(n-n/3-1)*(n-n/3)/2<<endl;
 	return 0;
}

B 题目链接:Problem - B - Codeforces

 input:

2 4
X..X
X.X.
X.X.
.X..

output:

X.XX
.X..

题意:

 给n*m个格子的扫雷地图A和图B,输入中‘X’代表地雷,‘.’代表没有地雷。对于每个无雷点,都可以计算一个数字,数字的含义为周围所有格子的地雷数量(包括对角的四个格子)。现有一种操作,可以令任一格子的状态相反(有雷变无雷,无雷变有雷),这种操作最多不超过 m*n/2 (下取整) 次。要求对图B经若干次操作后,使得图A所有无雷点数字的加和等于图B所有无雷点数字的加和。输出更改后的图B。

思路:

思维题。

首先,明显可以得出,我们只需要把图B变成完全和图A一样即可,但是存在一个问题,如果图A和图B差距大的话,m*n/2 (下取整) 次数不够用。

造了几个样例以后发现,有一个比较有趣的现象:当构造一个图,与原图完全相反时,得到的无雷点数字之和与原图竟然一样!(不知道如何用数学证明/(ㄒoㄒ)/~~)

所以直接比较图A和图B有几个点不同,小于m*n/2 (下取整)就直接输出图A,否则输出图A的反

代码如下:

#include<bits/stdc++.h>
#define endl "\n"
using namespace std;
const int N=1010;
char a[N][N],b[N][N];
 
int n,m;
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	cin>>n>>m;
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=m;j++)
		{
			cin>>a[i][j]; 
		}
	}
	int cnt=0;
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=m;j++)
		{
			cin>>b[i][j];
			if(a[i][j]!=b[i][j])
				++cnt; 
		}
	}
	if(cnt<=(n*m)/2)
	{
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=m;j++)
			{
				cout<<a[i][j]; 
			}
			cout<<endl;
		}
	}
	else
	{
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=m;j++)
			{
				if(a[i][j]=='.')
					cout<<'X';
				else
				    cout<<'.'; 
			}
			cout<<endl;
		}		
	}
	return 0;
}

D 题目链接:Problem - D - Codeforces

input:

2
10000.0 1.0 0.001 9999.0 0.001
4306.063 4079.874 0.607 1033.423 0.847

 output:

5001000.0000000000
3827.8370013755

题意:

有一条长度为 n 的路,第一个人在位置 p1 ,速度为 v1 ,第二个人在位置 p2 ,速度为 v2 ,问两个人走的路径完全覆盖整条路的最短时间是多少(答案精度在1e-6以内即可)。

思路:

和队友分析了一通,最后将一堆情况整合成了三种情况。

情况一:其中某一个人速度巨快,直接一个人走完所有路。

情况二:两个人相向而行,分别走到路的两端。

情况三:以某一个中心点为界,两个人各走一段路(这个点一定在 p1 , p2 之间)。

三种情况取最优解即可。

情况一和二我们可以直接写出式子,对于情况三,我们需要讨论中心点在哪里。

对于情况三,我们的做法是直接三分求极值,结果也是对的(注意,三分时精度太高会超时!!训练后试代码发现了这个问题,训练中跟队友说开1e-12做,幸好后来改成了1e-8)。训练中队友提到两个人同时走完路程是最优的,这一点我没有加以利用。赛后也看了一下其他大佬的题解,发现他们利用这一点直接二分,让两个人的用时趋近平衡,最后得到答案。

我们的三分代码如下:

#include<bits/stdc++.h>
using namespace std;
double p1, p2, v1, v2;
double n;

double get(double x)
{
	double x1=(x+min(p1,x-p1))/v1;
	double x2=(n-x+min(p2-x,n-p2))/v2;
	return max(x1,x2);
}

int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int t; 
	cin>>t;
	while(t--)
	{
		cin>>n>>p1>>v1>>p2>>v2;
		if(p1>p2) 
			swap(p1,p2),swap(v1,v2);
		double l=p1,r=p2;
		double mid; 
		double ans = 1e18;
		while(r-l>1e-8)
		{
			mid=(l+r)/2;
			double mid1=(mid+l)/2;
			ans=min(ans,get(mid));
			ans=min(ans,get(mid1));
			if(get(mid)>get(mid1))
			{
				r=mid;
			}
			else
			{
				l=mid1;
			}
		}
		double sglTime=min((n+min(p1,n-p1))/v1,(n+min(p2,n-p2))/v2);
		double dblTime=max((n-p1)/v1,p2/v2);
		ans=min(ans,sglTime);
		ans=min(ans,dblTime);
		cout<<setprecision(20)<<ans<<endl;
	} 
}

M 题目链接:Problem - M - Codeforces

 

input:

2
3 0
data/train
data/test
model
3 1
data/train
data/test
model
data/sample

output:

2
3

题意:

现在有一个大文件夹,里面有一些文件和子文件夹,子文件夹里又有一些文件和子文件夹(文件夹都不是空的)。现在要将这些文件上传,但是有一些文件可以忽略,不用上传,有一些文件需要保护,一定要上传。每次忽略,我们可以忽略一个文件,或直接忽略一个文件夹的所有内容(包括所有文件和子文件夹),前提是里面不存在任何受保护的文件。另外,不能直接忽略这个大文件夹。现给出n个需要忽略文件的路径和m个受保护文件的路径,问最小要操作几次可以忽略掉所有指定文件。

思路:

对图没啥思路,这题基本是一窍不通,只是大概能想出来该怎么做却不会实现。这里贴一下队友的代码吧/(ㄒoㄒ)/~~

#include<bits/stdc++.h>
using namespace std;
const int MAXN=10001;
int T,n,k,num,ans;
struct node
{
	string s;
	bool f;
}a[MAXN];
vector<int> e[MAXN];
// 1 is keep
bool up(int u)
{
//	cout<<"ss"<<a[u].s<<endl; 
	if(e[u].size() == 0 )
	{
		return a[u].f;
	}
	
	bool flag = 0;
	for(int i = 0 ; i < e[u].size() ; i ++ ){
		if( up(e[u][i]) == true ){
			flag = true;
		}
	}
	if(flag == false){
		a[u].f = 0;
	}else a[u].f = 1;
	return a[u].f;
//	cout << a[u].s << "|"<< ' ' << a[u].f << endl;
}

int down(int u){
	if(a[u].f == 0) {
		return 1;
	}
	int sum=0;
	for(int i = 0 ; i < e[u].size() ; i ++ ){
		sum+=down(e[u][i]);
	}
//	cout<<"now: "<<a[u].s<<" sum: "<<sum<<endl;
	return sum;
}

void solve()
{
	cin>>n>>k;
	string s,t;
	for(int i=1;i<=num;i++) a[i].f=0,e[i]=vector<int>();
	num=1;ans = 0;
	a[1].s="main";
	for(int i=1;i<=n;i++)
	{
		cin>>s;
		int pre=0,fa=1;
		for(int j=0;j<s.length();j++)
		{
			if(s[j]=='/')
			{
				t=s.substr(pre,j-pre);
//				cout<<t<<"/"<<endl;
				pre=j+1;
				bool f=0;
				for(int u=0;u<e[fa].size();u++)
				{
					if(a[e[fa][u]].s==t)
					{
						f=1;
						fa=e[fa][u];
						break;
					}
				}
				if(!f)
				{
					a[++num].s=t;
					a[num].f=0;
					e[fa].push_back(num);
					fa=num;
				}
			}
		}
		t=s.substr(pre,s.length()-pre);
//		cout<<t<<"/"<<endl;
		a[++num].s=t;
		e[fa].push_back(num);
		a[num].f=0;
	}
	for(int i=1;i<=k;i++)
	{
		cin>>s;
		int pre=0,fa=1;
		for(int j=0;j<s.length();j++)
		{
			if(s[j]=='/')
			{
				t=s.substr(pre,j-pre);
//					cout<<t<<endl;
				pre=j+1;
				bool f=0;
				for(int u=0;u<e[fa].size();u++)
				{
					if(a[e[fa][u]].s==t)
					{
						f=1;
						fa=e[fa][u];
						break;
					}
				}
				if(!f)
				{
					a[++num].s=t;
					a[num].f=0;
					e[fa].push_back(num);
					fa=num;
				}
			}
		}
		t=s.substr(pre,s.length()-pre);
//			cout<<t<<endl;
		a[++num].s=t;
		e[fa].push_back(num);
		a[num].f=1;
	}
	up(1);
//	down(1);
	a[1].f=1;
	cout << down(1) << endl;
}
int main(){
	ios::sync_with_stdio(false);
	int _ ; cin >> _;
	while(_--)
	{
		solve();
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值