2019CCPC-江西省赛(重现赛)- 感谢南昌大学

先来简单地说一这套题我的收获:
1.再也不想使用cin和cout了,D题当时关闭同流后,用的cin,结果还是超时,下来后把cin换成scanf后,A了。所以就是还是scanf和printf好用,虽然敲的麻烦但是好用!
2.最近一段时间得好好学习DP,这套题不暴力就DP…阔是我的DP学的是真的差
3.强制类型转换有精度损失

A–Cotree

题意:给你两颗树,要求你在两颗树分别找一个点连成一条边,使得这两颗树连起来的新树结点两两距离之和最小
思路:借用强哥的思路,先把俩颗树分出来->分别求出每个树的重心->连接重心->求新树俩俩节点的距离(重心的作用:树的所有节点到重心的距离和最小)

#include <iostream>
#include <vector>
using namespace std;
typedef long long ll;

const ll maxn = 1e5+10;

ll N,sumT1,sumT2,sumT3,H1,H2,mx;//结点总数,树1的结点数,树2的结点数,新树的结点数,树1的重心,树2的重心
ll fa[maxn];
ll sz[maxn];//sz[i]:以i为根结点的树的结点数
vector<ll> ve[maxn];

ll find(ll x){
    return x == fa[x]? x:fa[x] = find(fa[x]);
}
void join(ll x,ll y){
    ll fx = find(x),fy = find(y);
    if(fx != fy) fa[fx] = fy;
}

ll DFS_coun(ll u,ll fa = -1){
    ll sum = 1;
    for(ll i = 0;i<ve[u].size();i++){
        if(ve[u][i] == fa) continue;
        sum += DFS_coun(ve[u][i],u);
    }
    return sz[u] = sum;
}

void DFS_find(ll u,ll sum,ll &h,ll fa = -1){
    ll m = max(sum-sz[u],0LL);
    for(ll i = 0;i<ve[u].size();i++)
        if(ve[u][i]!=fa) m = max(m,sz[ve[u][i]]);
    if(m<mx) h = u,mx = m;
    for(ll i = 0;i<ve[u].size();i++){
        int v = ve[u][i];
        if(v != fa) DFS_find(v,sum,h,u);
    }
}

ll DFS_dis(ll u,ll fa = -1){
    ll sum = 0;
    for(ll i = 0;i<ve[u].size();i++){
        ll v = ve[u][i];
        if(v == fa) continue;
        sum += sz[v]*(sumT3-sz[v]);
        sum += DFS_dis(v,u);
    }
    return sum;
}

int main(){
    cin>>N;
    for(ll i = 1;i<=N;i++) fa[i] = i;
    ll a,b;
    for(ll i = 1;i<=N-2;i++){
        scanf("%lld%lld",&a,&b);
        ve[a].push_back(b);
        ve[b].push_back(a);
        join(a,b);
    }
    ll root1 = -1,root2 = -1;
    for(ll i = 1;i<=N;i++) find(i);
    for(ll i  = 1;i<=N;i++){
        if(fa[i] == i){
            if(root1 == -1) root1 = i;
            else root2 = i;
        }
    }
    sumT1 = DFS_coun(root1);
    sumT2 = DFS_coun(root2);
    H1 = root1,H2 = root2;
    sumT3 = sumT1+sumT2;
    mx = 0x3f3f3f3f;
    DFS_find(root1,sumT1,H1);
    mx = 0x3f3f3f3f;
    DFS_find(root2,sumT2,H2);
    ve[H1].push_back(H2);
    ve[H2].push_back(H1);

    DFS_coun(H1);
    ll res = DFS_dis(H1);
    cout<<res<<endl;
    return 0;
}

B–Math

C - Trap

D - Wave

这个题意也很简单,直接给一个代码吧!
这个代码有点LOW,但是大家可以参考一下,这个题还有更加简单的暴力以及DP!!
注:就是这个题,关闭同流都不行,但scanf行!

#include<iostream>
#include<algorithm>
#include<vector>
#include<utility>
using namespace std;
int n,m;
vector <pair<int,int> > G[200];
typedef long long ll;
int cmp(pair<int,int> a,pair<int,int> b)
{
	return a.first<b.first;
}
int main()
{
	//ios::sync_with_stdio(false);
	scanf("%d%d",&n,&m);
	//cin>>n>>m;
	int x;
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&x);
		//cin>>x;
		G[x].push_back(make_pair(i,x));
	}
	int maxn=0;
	for(int i=1;i<=m;i++)
	{
		for(int j=i+1;j<=m;j++)
		{
			if(G[i].size()&&G[j].size())
			{
				vector<pair<int,int> > v;
				for(int z=0;z<G[i].size();z++)
					v.push_back(G[i][z]);
				for(int z=0;z<G[j].size();z++)
					v.push_back(G[j][z]);
				sort(v.begin(),v.end(),cmp);
				int flag;	int sum=0;
                 for(int z=0;z<v.size();z++)
                 {
                     if(z==0)
					 {
					 	sum++;
						flag=v[z].second;
					 }
                     else if(v[z].second!=flag)
					 {
					 	sum++;
						flag=v[z].second;
					 }
                 }
                 maxn=max(maxn,sum);
			}
		}
	}
	printf("%d\n",maxn);
	//cout<<maxn<<endl;
	return 0;
}

E - Packing

F - String

这个题嘛,个人的意见就是一定要理解对题意,人家的意思是一个字符串里面随便选四个字母,问是avin的概率,而且人家的字符串也没有别的字母。所以就是统计每个字母出现的次数,然后把选每个字母的概率统统乘起来就行。当时没理解对,写的有点慌乱,凑合的看一下吧!还有就是要约分!!!

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main()
{
	ios::sync_with_stdio(false);
	int m;
	string s;
	cin>>m>>s; 
	int flag=-1;
	int a=0;
	int v=0;
	int  i=0;
	int n=0;
	for(int j=0;j<m;j++)
	{
		if(s[j]=='a')
			a++;
		if(s[j]=='v')
			v++;
		if(s[j]=='i')
			i++;
		if(s[j]=='n')
			n++;
	}
	if(a&&v&&i&&n)
	{
		ll x=m*m*m*m;
		ll y=a*v*i*n;
		cout<<(y/__gcd(x,y))<<"/"<<(x/__gcd(x,y))<<endl;
	}
	else
		cout<<"0/1"<<endl;
	return 0;
}

G - Traffic

先发一张图片纪念一下当时SB的我!!!
在这里插入图片描述
其实也不是SB,百因必有果,我的报应就是英语没学好!!!
题意就是东西方向一堆车,南北方向一堆车,问南北方向的车最少等多长时间才能不撞车!!!注意人家说的是一起等多长时间!!!

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main()
{
	ios::sync_with_stdio(false);
	int n,m,a[3000],b[3000],c[3000];
	cin>>n>>m;
	for(int i=0;i<n;i++)
		cin>>a[i];
	for(int i=0;i<m;i++)
		cin>>b[i];
	int sum=0;
	for(int i=0;i<n;i++)
	{
		for(int j=0;j<m;j++)
		{
			if(a[i]==b[j])
			{
				for(int j=0;j<m;j++)
					b[j]++;
				sum++;
				i=0;
				break;
			}
		}
	}
	cout<<sum<<endl;	
	return 0;
}

H - Rng

直接打表猜一下就行,一个简单的逆元!!!

#include <bits/stdc++.h>
using namespace std;
const int mod = 1e9 + 7;
long long qk(long long a, long long n) 
{
    long long res = 1;
    while (n)
    {
        if (n & 1)res = res * a % mod;
        n >>= 1;
        a = a * a % mod;
    }
    return res;
}
 
int main() 
{
    long long n;
    cin >> n;
    cout << (n + 1) * qk(2 * n, mod - 2) % mod << endl;
    return 0;
}

I - Budget

这个题意也简单,但是自己真的是学识短浅,想的1000,再/1000;结果过程中有强制类型转换,有精度损失!!!!!!其实这个题直接用字符串就行了,但是当时是真的着急+懵…下面是代码。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main()
{
//	ios::sync_with_stdio(false);
	int n;	double sum=0;
	string s;	cin>>n;
	for(int i=0;i<n;i++)
	{
		cin>>s;
		if(s[s.length()-1]>='5')
			sum=sum+(58-(int)s[s.length()-1]);
		else
			sum=sum-(s[s.length()-1]-'0');	
	}
	sum=sum*1.0/1000;
	printf("%.3lf\n",sum);
	return 0;
}

J - Worker

也没什么好说的,就 就求出LCM就OK了。直接看代码就理解了!

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll a[101000];
ll b[101000];
ll lcm(ll a,ll b)
{
	return a*b/__gcd(a,b);
}
int main()
{
	ios::sync_with_stdio(false);
	ll m,n;  cin>>n>>m;
	a[0]=1;
	ll bb,cc;
	cin>>a[1];
	ll aa=a[1];
	ll sum=a[1];
	for(int i=2;i<=n;i++)
	{
		cin>>a[i];
		sum=lcm(sum,a[i]);
	}
	ll tt=0;
	for(int i=1;i<=n;i++)
	{
		b[i]=sum/a[i];
		tt=tt+b[i];
	}
	
	if(m%tt==0)
	{
		cout<<"Yes"<<endl;
		for(int i=1;i<=n;i++)
			if(i==n)
				cout<<b[i]*(m/tt)<<endl;
			else
				cout<<b[i]*(m/tt)<<" ";
	}
	else
		cout<<"No"<<endl;
	return 0;
}

K - Class

这个题一个是一个最水的题,题意很简单,解题思路就是解俩个方程。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main()
{
	ios::sync_with_stdio(false);
	double x,y;
	cin>>x>>y;
	double  a=(x+y)/2.0;
	double b=(x-y)/2.0;
	cout<<a*b<<endl;
	return 0;
}
发布了41 篇原创文章 · 获赞 5 · 访问量 2271

猜你喜欢

转载自blog.csdn.net/mumuhaoshuai/article/details/103019473