牛客练习赛41

B题:https://ac.nowcoder.com/acm/contest/373/B

分析:一个简单的计数dp,比赛时居然在dfs...

状态转移dp[i][j]=dp[i-1][j-a[i]]+dp[i-1][-j],dp[i][j]表示第i回合分数为j,由于有-j,可把分数整体加上一个大数k,并且由于空间不够要用滚动数组,特判去掉666的情况。

Ac code:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll dp[2][300*1500];
int a[305];
int n;
const int k=700*305;
const ll mod=1e8+7;
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    dp[0][k]=1;
    for(int i=1;i<=n;i++)
        for(int j=-666*n;j<=666*n;j++){
          if(j==666) continue;
          dp[i&1][j+k]=(dp[(i-1)&1][j-a[i]+k]+dp[(i-1)&1][-j+k])%mod;
      }
    printf("%lld\n",dp[n&1][-666+k]);
    return 0;
} 

题目:https://ac.nowcoder.com/acm/contest/373/C

分析:一个简单的计数并查集

Ac code:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+5;
int parent[maxn];
ll a[maxn];
void init(int n)
{
	for(int i=1;i<=n;i++)
	  parent[i]=i;
}
int fnd(int x)
{
	return parent[x]!=x?parent[x]=fnd(parent[x]):x;
}
vector<ll>ans;
bool cmp(ll a,ll b)
{
	return a>b;
}
int main()
{
	int n,m,v;
	scanf("%d%d",&n,&m);
	init(n);
	for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
	for(int i=1;i<=n;i++){
		scanf("%d",&v);
		int fx=fnd(i),fy=fnd(v);
		if(fx!=fy)
		  parent[fy]=fx,a[fx]+=a[fy];///父亲加上儿子拥有的数量
	}
	for(int i=1;i<=n;i++)
	  if(i==parent[i])
	     ans.push_back(a[i]);
	sort(ans.begin(),ans.end(),cmp);
	ll sum=0;
	for(int i=0;i<min(m,(int)ans.size());i++)
	  sum+=ans[i];
	printf("%lld\n",sum);
	return 0;
}

题目:https://ac.nowcoder.com/acm/contest/373/D

分析:维护一个差异度d数组,把n个字符串作为起点,每个字符串的每个二进制位翻转,将d[i]维护成最小,则相似度为m-d[i]最大,求2^m个状态下的最小值

Ac code:

#include<bits/stdc++.h>
using namespace std;
queue<int>q;
int d[2000005];
int main()
{
	int n,m;
	char s[25];
	scanf("%d%d%*c",&n,&m);
	for(int i=0;i<(1<<m);i++) d[i]=m;///d为状态i下的差异度 
	for(int i=1;i<=n;i++){
		scanf("%s",s);
		int val=0;
		for(int j=0;j<m;j++)
		  if(s[j]=='1')
		    val|=(1<<(m-1-j));  
		  d[val]=0;///设这n个字符为起始差异度 
		  q.push(val);
	}
	while(!q.empty()){
		int cur=q.front();
		q.pop();
		for(int i=0;i<m;i++)
		{
		  	int nex=cur^(1<<i);
		  	if(d[nex]>d[cur]+1){///维护d为最小差异度,m-d[i]就是最大了 
		  		d[nex]=d[cur]+1;
		  		q.push(nex);
			}
		}
	}
	int ans=40;
	for(int i=0;i<(1<<m);i++)
	  ans=min(ans,m-d[i]);
	printf("%d\n",ans);
	return 0;
}

题目:https://ac.nowcoder.com/acm/contest/373/E

分析:纯公式题,球冠的体积:V=pi*h*h*(R-h/3)=pi*h*(3*r*r+h*h)/6

其中h为球冠的高,即垂直于截面的直径,R为球的半径,r为截面圆的半径。

补充公式:球冠表面积S=2*pi*R*h

Ac code:

#include<bits/stdc++.h>
using namespace std;
const long double pi=4.0*atan(1.0); 
long double getv(long double R,long double h)
{
	return pi*h*h*(R-h/3.0);
}
int main()
{
	long double x1,y1,z1,x2,y2,z2,R,r;
	scanf("%Lf%Lf%Lf%Lf%Lf%Lf%Lf%Lf",&x1,&y1,&z1,&R,&x2,&y2,&z2,&r);
	long double h=sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)+(z1-z2)*(z1-z2));
	if(R<r) swap(R,r);
	if(R-r>=h){
		printf("%.7Lf\n",4.0/3*pi*R*R*R);
		return 0;
	}
	if(R+r<=h){
		return 0*printf("%.7Lf\n",pi*4.0/3*(R*R*R+r*r*r));
	}
	long double x=(R*R-r*r+h*h)/(2*h);
	long double v1=getv(R,x+R);
	long double v2=getv(r,r+h-x);
	long double ans=v1+v2;
	printf("%.7Lf\n",ans);
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值