2020牛客寒假算法基础集训营1

A - honoka和格点三角形
传送
题意:N*M大小的格点 可以组成多少面积大小为1且顶点在格点上的三角形;

#include<bits/stdc++.h>

using namespace std;
const int mod = 1e9+7;

int main()
{
	long long  n,m,ans=0;
	cin>>n>>m;                                        //局部代替整体
	ans=(ans+(m-2)*(n-1)*4%mod +(n-2)*(m-1)*4%mod)%mod; //两条边都平行于坐标轴 
	ans=(ans+2*(m-2)*(m-2)%mod*(n-1)%mod+2*(n-2)*(n-2)%mod*(m-1)%mod)%mod; //一条边平行(底为2高1) 
	ans=(ans+2*(m-1)*(m-2)%mod*(n-2)%mod+2*(n-1)*(n-2)%mod*(m-2)%mod)%mod;//一条边平行(底为1高2)
	cout<<ans<<endl;
	return 0;
}

C - umi和弓道
传送
在这里插入图片描述
题解:分别求出两点之间与坐标轴的交点(如果存在的话),然后双指针遍历两个坐标轴维护最小值,只要某一条轴能挡住n-k个点就能成功;

#include<bits/stdc++.h>

using namespace std;

int main()
{
	double X,Y;
	cin>>X>>Y;
	int n,k;
	cin>>n>>k;
	k=n-k;		//有一点小绕
	double x,y,num=0;
	vector<double> vx,vy;
	for(int i=0;i<n;i++){
		cin>>x>>y;
//		double kk = (Y-y)/(X-x);		//解法一
//		if(x*X>0&&y*Y>0) num++;
//		else if(X==x) vx.push_back(x);
//		else if(Y==y) vy.push_back(y);
//		else if(X*x>0&&Y*y<0) vx.push_back(-y/kk+x);
//		else if(X*x<0&&Y*y>0) vy.push_back(kk*(-x)+y);
//		else {
//			vx.push_back(-y/kk+x);
//			vy.push_back(kk*(-x)+y);
//		}
		if(X*x<0) vy.push_back(y-x*(Y-y)/(X-x));	//解法二
		if(Y*y<0) vx.push_back(x-y*(X-x)/(Y-y));
	}
	double ans=1e18;
	sort(vx.begin() ,vx.end() );
	sort(vy.begin() ,vy.end() );
	for(int i=0,j=k-1;j<vx.size() ;i++,j++){
		ans = min(vx[j] - vx[i],ans);
	}
	for(int i=0,j=k-1;j<vy.size() ;i++,j++){
		ans = min(vy[j] - vy[i],ans);
	}
	if(ans==1e18) printf("-1\n");		//不管x轴还是y轴,只要能挡住n-k个点 就算成功了;
	else printf("%.8lf\n",ans);

	return 0;
}

F - maki和tree
传送门

主要在于理解题意,和建立模型;
在这里插入图片描述
计数:ans += x1+x2+x3+x2x1+x3(x1+x2) ;

#include<bits/stdc++.h>
#define LL long long
using namespace std;
const int N = 1e5+7;

char s[N];
vector<int> G[N];
LL ans=0,num=0;

void DFS(int p,int fa)
{
	if(s[p]=='B') return ;
	num++;
	for(int i=0;i<G[p].size() ;i++)
		if(G[p][i]!=fa) DFS(G[p][i],p);
}

int main()
{
	int n ;
	scanf("%d",&n);
	int c = n;
	scanf("%s",s+1);
	while(--c){
		int x,y;
		scanf("%d%d",&x,&y);
		G[x].push_back(y); 
		G[y].push_back(x); 
	}
	for(int i=1;i<=n;i++){
		LL A=0;
		if(s[i]=='B'){
			for(int j=0;j<G[i].size() ;j++){
				num=0;
				DFS(G[i][j],0);
				ans+=A*num+num;
				A+=num;
			}
		}
	}
	cout<<ans<<endl;
	return 0;
}

H - nozomi和字符串
传送

题解:贪心,将01字符串分离成0串和1串(处理时将开头置为-1,末尾置为n),分别双指针求区间长度为k的最大值;

#include<bits/stdc++.h>

using namespace std;

int main()
{
	int n,k;
	cin>>n>>k;
	vector<int> v0,v1;
	string s;
	cin>>s;
	v0.push_back(-1);v1.push_back(-1);  
	for(int i=0;i<n ;i++)
		if(s[i]=='0') v0.push_back(i); 
		else v1.push_back(i);
	v0.push_back(n),v1.push_back(n);  
	
	int ans=0,num0 = v0.size() ,num1 = v1.size() ;
	
	if(num0-2<=k||num1-2<=k) ans=n;  //必不可少,k过大时不会进入循环;
	for(int i=1,j=k;j<num0-1 ;i++,j++)
		ans = max(ans , v0[j+1]-v0[i-1]-1);
	
	for(int i=1,j=k;j<num1-1 ;i++,j++)
		ans = max(ans , v1[j+1]-v1[i-1]-1);
	
	cout<<ans<<endl;
	return 0;
}

I - nico和niconiconi

传送
在这里插入图片描述
题解:简单动态规划;

#include<bits/stdc++.h>
#define LL long long

using namespace std;

LL n,a,b,c,dp[300010];

int main()
{
	cin>>n>>a>>b>>c;
	getchar();
	string s;
	getline(cin,s);
	for(int i=0;i<n;i++){
		dp[i+1] = dp[i];
		if(i>=3 && s.substr(i-3,4)=="nico")
			dp[i+1] = max(dp[i+1],dp[i-3]+a);
		if(i>=5 && s.substr(i-5,6)=="niconi" )
			dp[i+1] = max(dp[i+1],dp[i-5]+b);
		if(i>=9 && s.substr(i-9,10)=="niconiconi")
			dp[i+1] = max(dp[i+1],dp[i-9]+c);
	}
	cout<<dp[n]<<endl;
	return 0;
 } 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值