您的位置:首页 > 其它

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

2020-02-02 19:45 190 查看

先来简单地说一这套题我的收获:
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

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

[h2]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;
}
  • 点赞
  • 收藏
  • 分享
  • 文章举报
〆℡小短腿走快点ゝ 发布了30 篇原创文章 · 获赞 1 · 访问量 1410 私信 关注
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐