Cotree
题意:有两棵树,一共n个点,在两棵树上连一条边,使得他们变成一棵树,问如何连边使得他们题目中的式子最小。
思路:树中所有点到某个点的距离和中,到重心的距离和最小,先求得重心,然后求连接重心后节点的两两距离和即可。 摘自
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const int maxn=1e5+5;
const int maxm=3e5+5;
struct edge{
int u,v,next;
}e[maxm];
int head[maxn],cnt;
void addedge(int u,int v){
e[cnt].u=u;
e[cnt].v=v;
e[cnt].next=head[u];
head[u]=cnt++;
}
int n,vis[maxn],tot,p,minnum;
void dfs0(int u){
if(vis[u])
return;
vis[u]=1;
tot++;
for(int i=head[u];i!=-1;i=e[i].next)
dfs0(e[i].v);
}
int dfs1(int u,int pre,int N){
int sum=0,max_sub=0;
for(int i=head[u];i!=-1;i=e[i].next){
int v=e[i].v;
if(v==pre)
continue;
int t=dfs1(v,u,N);
max_sub=max(max_sub,t);
sum+=t;
}
max_sub=max(max_sub,N-sum-1);
if(max_sub<minnum){
minnum=max_sub;
p=u;
}
return sum+1;
}
ll ans=0;
int dfs2(int u,int pre){
int sum=0;
for(int i=head[u];i!=-1;i=e[i].next){
int v=e[i].v;
if(v==pre)
continue;
int t=dfs2(v,u);
ans+=1ll*t*(n-t);
sum+=t;
}
return sum+1;
}
int main(){
memset(head,-1,sizeof(head));
cnt=0;
scanf("%d",&n);
for(int i=1;i<=n-2;i++){
int u,v;
scanf("%d%d",&u,&v);
addedge(u,v);
addedge(v,u);
}
int s1,s2,n1,n2;
for(int i=1;i<=n;i++){
if(!vis[i]){
tot=0;
dfs0(i);
if(i==1){
s1=i;
n1=tot;
}
else{
s2=i;
n2=tot;
}
}
}
int g1,g2;
minnum=inf;
dfs1(s1,-1,n1);
g1=p;
minnum=inf;
dfs1(s2,-1,n2);
g2=p;
addedge(g1,g2);
addedge(g2,g1);
ans=0;
dfs2(1,-1);
printf("%lld\n",ans);
return 0;
}
Wave
题意:构造一个序列,使得奇数位置上的数完全一样,并且偶数上的也一样,奇数上的和偶数上的数不同,求该序列的最长长度。
思路:枚举两个数。
#include<bits/stdc++.h>
using namespace std;
int a[100005];
typedef pair<int,int> p;
vector<p> cnt[105];
int cmp(p x,p y){
return x.second<y.second;
}
int main(){
int n,c;
while(~scanf("%d%d",&n,&c)){
memset(cnt,0,sizeof(cnt));
int x;
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
cnt[a[i]].push_back({a[i],i});
}
int mx=0;
for(int i=1;i<=c;i++){
for(int j=i+1;j<=c;j++){
if(cnt[i].size()&&cnt[j].size()){
vector<p>v;
for(int k=0;k<cnt[i].size();k++)
v.push_back(cnt[i][k]);
for(int k=0;k<cnt[j].size();k++)
v.push_back(cnt[j][k]);
sort(v.begin(),v.end(),cmp);
int f,s=0;
for(int k=0;k<v.size();k++){
if(!k)
s++,f=v[k].first;
else if(v[k].first!=f)
s++,f=v[k].first;
}
mx=max(s,mx);
}
}
}
printf("%d\n",mx);
}
}
String
题意:给定长度为n的字符串,问任选4个能组成avin的概率
思路:分母为n^4,分子根据乘法原理的求得。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int a[30];
char s[205];
int main(){
int n;
while(~scanf("%d",&n)){
memset(a,0,sizeof(a));
scanf("%s",s);
for(int i=0;i<n;i++)
a[s[i]-'a']++;
int s1=a['a'-'a'],s2=a['v'-'a'],s3=a['i'-'a'],s4=a['n'-'a'];
int t1=n*n*n*n;
int sum=s1*s2*s3*s4;
if(sum==0){
printf("0/1\n");
continue;
}
int t=__gcd(sum,t1);
sum/=t,t1/=t;
printf("%d/%d\n",sum,t1);
}
return 0;
}
Traffic
题意:东西和南北方向有车子通过,问推迟最少的时间使得两个方向的车子不会相撞。
思路:枚举可能相撞的x,取使得不会相撞的最少值
#include<bits/stdc++.h>
using namespace std;
int a[1005],b[1005],vis[1000005];
int main(){
int n,m;
while(~scanf("%d%d",&n,&m)){
memset(vis,0,sizeof(vis));
for(int i=0;i<n;i++)
scanf("%d",&a[i]);
for(int i=0;i<m;i++)
scanf("%d",&b[i]);
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
if(a[i]>=b[j])
vis[a[i]-b[j]]=1;
for(int i=0;;i++)
if(!vis[i]){
printf("%d\n",i);
break;
}
}
return 0;
}
Rng
题意:在区间里选择两个区间,问区间相交的概率。
思路:可以通过求出区间不想交的概率求出相交的概率,假设区间长度为0,先选第一个线段的右端点有n种可能,再选第二个线段的左端点,有(n-1)种可能,重复算了两次,所以概率为1-(n*(n-1))/(2*n*n)
#include<bits/stdc++.h>
using namespace std;
const int mod=1e9+7;
typedef long long ll;
ll inv(ll b){return b==1?1:(mod-mod/b)*inv(mod%b)%mod;}
int main(){
ll n;
while(~scanf("%lld",&n)){
printf("%lld\n",(n+1)*inv(2*n)%mod);
}
}
Budget
题意:四舍五入第3位小数,问丢失了多少精度
#include<bits/stdc++.h>
using namespace std;
double a[1005];
char s[30];
int main(){
int n;
while(~scanf("%d",&n)){
double s1=0,s2=0;
int sum=0;
for(int i=0;i<n;i++){
scanf("%s",s);
int l=strlen(s);
if(s[l-1]-'0'>=5)
sum+=10-(s[l-1]-'0');
else sum-=(s[l-1]-'0');
}
printf("%.3lf\n",(double)sum/1000.0);
}
}
Worker
题意:问能否分配工人使得每个仓库的工作量相同。
思路:求的所以数的最小公倍数即可。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll a[1005],b[1005];
int main(){
int n;
ll m;
while(~scanf("%d%lld",&n,&m)){
a[0]=0;
for(int i=1;i<=n;i++)
scanf("%lld",&a[i]),b[i]=a[i];
for(int i=1;i<=n;i++){
if(i!=1){
a[i]=a[i]/__gcd(a[i],a[i-1])*a[i-1];
}
}
ll sum=0;
for(int i=1;i<=n;i++)
sum+=a[n]/b[i];
if(m%sum==0&&m>=sum){
printf("Yes\n");
for(int i=1;i<=n-1;i++)
printf("%lld ",m/sum*(a[n]/b[i]));
printf("%lld\n",m/sum*(a[n]/b[n]));
}
else printf("No\n");
}
}
Class
签到题
#include<bits/stdc++.h>
using namespace std;
int main(){
int x,y;
while(~scanf("%d%d",&x,&y)){
int a=(x+y)/2,b=(x-y)/2;
printf("%d\n",a*b);
}
}