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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章