牛客寒假算法基础集训营5 解题报告(未完成)

比赛链接:https://ac.nowcoder.com/acm/contest/331#question

A 判断能不能形成三角形就可以,如果不能形成三角形那么最短距离就是起点和终点距离减去L1+L2

#include<bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f;
int main()
{
	double x,y,l3;
	int l1,l2, t;
	std::ios::sync_with_stdio(false);
	cin >> l1 >> l2;
	cin >> t;
	
	while(t--)
	{
		cin >> x >> y;
		l3 = sqrt((double)x*x+y*y);
		if(l3 > l1 && l3 >l2)
		{
			if(l1+l2>=l3)
			{
				printf("0.000000\n");
			}
			else
			{
				printf("%.6f\n", l3-l1-l2);
			}
		}
		else if(l2 > l1 && l2 >l3)
		{
			if(l1+l3>=l2)
			{
				printf("0.000000\n");
			}
			else
			{
				printf("%.6f\n", l2-l1-l3);
			}
		}
		else if(l1 > l3 && l1 >l2)
		{
			if(l2+l3>=l1)
			{
				printf("0.000000\n");
			}
			else
			{
				printf("%.6f\n", l1-l2-l3);
			}
		}
		
	}

	return 0;
} 

B: 四个方向搜索一下就行,看了下别人的代码 才会写,这个方法很妙~

#include<bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f;
set<pair<int,int> >mp[2];
int d[8][2]={-1,0,1,0,0,-1,0,1,-1,-1,1,1,1,-1,-1,1},n,m,comp;

int access(int x,int y)
{
	if(x<=n&&y<=n&&x>0&&y>0)
		return 1;
	return 0;
}

int DFS(int x,int y,int num)
{
	int xx, yy,ans = 0,i;
	xx=x,yy=y;
	for(i=0;i<4;i++)
	{
		xx=xx+d[num][0];
		yy=yy+d[num][1];
		if(access(xx,yy)&&mp[comp].count(make_pair(xx,yy)))
			ans++;
		else break;
	}
	return ans;
}

int main()
{
	std::ios::sync_with_stdio(false);
	int i,x,y,ans;
	cin>>n>>m;
	while(m--)
	{
		comp=m%2;
		cin>>x>>y;
		mp[comp].insert(make_pair(x,y));
		if(mp[comp].size()<5&&comp%2==1) {cout<<"N"<<endl;continue;}
		for(i=0;i<8;i+=2)
		{
			ans=DFS(x,y,i)+DFS(x,y,i+1);
			if(ans>=4)break;
		}
		if(ans>=4)cout<<"Y"<<endl;
		else cout<<"N"<<endl;
	}

	return 0;
} 

C: 主要是要知道怎么走是最短路就行

n或m等于1   就一直走

n或m等于2  就是

其他情况就是   不过这里要判断 一下是横着走还是竖着走  有个条件就是(n/2)*(m-1)<=(m/2)*(n-1)   不过我也不知道为什么是这样判断,如果有知道的还请告知Thanks♪(・ω・)ノ

 

#include<bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f;
char mp[1005][1005];
int main()
{
	std::ios::sync_with_stdio(false);
	int n,m,k,stx=1,sty=1,enx=1,eny=1,i,j,flag=0;
	cin>>n>>m>>k;
	
	for(i=1;i<=n;i++){
		for(j=1;j<=m;j++)
		{
			mp[i][j]='x';
		}
	}
	mp[enx][eny]='.';
	if(n==1){
		for(i=2;i<=k+1;i++)
		{
			mp[1][i]='.';
			eny++;
		}
	} 
	else if(m==1){
		for(i=2;i<=k+1;i++)
		{
			mp[i][1]='.';
			enx++;
		}
	}
	else if(n==2){
		while(k)
		{
			if(k) enx++,k--,mp[enx][eny]='.';
			if(k) eny++,k--,mp[enx][eny]='.';
			if(k) eny++,k--,mp[enx][eny]='.';
			if(k) enx--,k--,mp[enx][eny]='.';
			if(k) eny++,k--,mp[enx][eny]='.';
			if(k) eny++,k--,mp[enx][eny]='.';
		}
		
	}
	else if(m==2){
		while(k)
		{
			if(k) eny++,k--,mp[enx][eny]='.';
			if(k) enx++,k--,mp[enx][eny]='.';
			if(k) enx++,k--,mp[enx][eny]='.';
			if(k) eny--,k--,mp[enx][eny]='.';
			if(k) enx++,k--,mp[enx][eny]='.';
			if(k) enx++,k--,mp[enx][eny]='.';
		}
		
	}
	else{
		if((n/2)*(m-1)<=(m/2)*(n-1)){
			while(k)
			{
				while(eny<m&&k) eny++,k--,mp[enx][eny]='.';
				if(k) enx++,k--,mp[enx][eny]='.';
				if(k) enx++,k--,mp[enx][eny]='.';
				while(eny>1&&k) eny--,k--,mp[enx][eny]='.';
				if(k) enx++,k--,mp[enx][eny]='.';
				if(k) enx++,k--,mp[enx][eny]='.';
			}
			
		} 
		else{
			while(k)
			{
				while(enx<n&&k) enx++,k--,mp[enx][eny]='.';
				if(k) eny++,k--,mp[enx][eny]='.';
				if(k) eny++,k--,mp[enx][eny]='.';
				while(enx>1&&k) enx--,k--,mp[enx][eny]='.';
				if(k) eny++,k--,mp[enx][eny]='.';
				if(k) eny++,k--,mp[enx][eny]='.';
			}
			
		}
		
	} 
	cout<<stx<<" "<<sty<<endl;
	cout<<enx<<" "<<eny<<endl;
	
	for(i=1;i<=n;i++)
	{
		for(j=1;j<=m;j++)
		{
			cout<<mp[i][j];
		}
		cout<<endl;
	}

	return 0;
} 

D: 把起点和终点还有可以传送的点全部放进vector容器里

然后排序,去重

有一个三重循环,前面两重循环是循环每个点,最后一重循环就是判断这两个点之间有没有传送法阵,如果有的话   

就是  dp[j]=min(dp[i]+1,dp[j]);

后面  dp[j] = min(dp[i] + __builtin_popcount(mp[j] - mp[i]), dp[j]);   就是i,j 两点的差  换成二进制中1的个数就是要走的路程

最后输出

#include<bits/stdc++.h>
using namespace std;
#define ll long long int 
const int INF = 0x3f3f3f3f;
int a[10005],b[10005];
vector<int>mp;
int dp[10005];
int main()
{
	std::ios::sync_with_stdio(false);
	int n,k,i,j,p;
	cin>>n>>k;
	mp.push_back(1);
	mp.push_back(n);
	for(i=0;i<k;i++)
	{
		cin>>a[i]>>b[i];
		mp.push_back(a[i]);
		mp.push_back(b[i]);
	}
	sort(mp.begin(),mp.end());
	mp.erase(unique(mp.begin(),mp.end()),mp.end());
	memset(dp,INF,sizeof(dp));
	dp[0]=0;
	for(i=0;i<mp.size();i++)
	{
		for(j=i+1;j<mp.size();j++)
		{
			for(p=0;p<k;p++)
			{
				if(mp[i]==a[p]&&mp[j]==b[p])
				{
					dp[j]=min(dp[i]+1,dp[j]);
				}
			}
			dp[j] = min(dp[i] + __builtin_popcount(mp[j] - mp[i]), dp[j]);
		}
	}
	cout<<dp[mp.size()-1]<<endl;
	  
	return 0;
} 

F: 看了很久才看懂题解

首先题目意思是说在子矩阵中的数字随意排列组合,有多少个子矩阵可以构成回文串

根据异或的性质,没有先后顺序,异或两次相当于没有异或

所以我们维护一下前缀异或

这里要注意

所以方法就是这样去判断是否是回文串,pre数组就是记录前缀异或的    num数组就是记录异或值出现的次数

还有一点就是要分组成回文串的是奇数还是偶数

上面那张图是偶数的情况

奇数的情况就是多了一个数字,只出现了一次,这一串回文串最后异或出来的结果就是这个只出现了一次的数字

所以我们循环一下0-9十个数字就行

 

#include<bits/stdc++.h>
using namespace std;
#define ll long long int 
const int INF = 0x3f3f3f3f;
char mp[2][1000005];
int pre[3][1000005];
ll num[3][1000005];
int main()
{
//	std::ios::sync_with_stdio(false);
	int n,i,j;
	ll ans=0;
	scanf("%d",&n);
	memset(num,0,sizeof(num));
	memset(pre,0,sizeof(pre));
	scanf("%s",mp[0]+1); 
	scanf("%s",mp[1]+1); 
		
	num[0][0]=num[1][0]=num[2][0]=1;
	for(i=1;i<=n;i++)
	{
		pre[0][i]=pre[0][i-1]^(1<<(mp[0][i]-'0'));
		pre[1][i]=pre[1][i-1]^(1<<(mp[1][i]-'0'));
		pre[2][i]=pre[2][i-1]^(1<<(mp[0][i]-'0'))^(1<<(mp[1][i]-'0'));
		ans+=num[0][pre[0][i]]+num[1][pre[1][i]]+num[2][pre[2][i]];//子矩阵中的数字是偶数时 
//		cout<<"qqq  "<<pre[0][i]<<"   "<<pre[1][i]<<"  "<<pre[2][i]<<endl;
//		cout<<"www  "<<num[0][pre[0][i]]<<"   "<<num[1][pre[1][i]]<<"   "<<num[2][pre[2][i]]<<endl;
//		cout<<"111    "<<ans<<endl;
		for(j=0;j<10;j++)
		{
			ans+=num[0][pre[0][i]^(1<<j)]+num[1][pre[1][i]^(1<<j)]+num[2][pre[2][i]^(1<<j)];//奇数个数字构成回文串 
//			cout<<"qqq  "<<num[0][pre[0][i]^(1<<j)]<<" "<<num[1][pre[1][i]^(1<<j)]<<"  "<<num[2][pre[2][i]^(1<<j)]<<endl;
//			cout<<"222    "<<ans<<endl;
		}
		num[0][pre[0][i]]++;
		num[1][pre[1][i]]++;
		num[2][pre[2][i]]++;
	}
	cout<<ans<<endl;
	

	return 0;
} 

 

G: 打表, 不过这个方法真是妙呀!

#include<bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = 1000000;
int prime[1000005],ans[1000005];
void is_prime()
{
	int i, j;
	memset(prime,0,sizeof(prime));
	memset(ans,INF,sizeof(ans));
	for(i = 1; i <= maxn; i++)
	{
		for(j = i; j <= maxn; j+=i)
		{
			prime[j]++;
			
		}
		ans[prime[i]] = min(ans[prime[i]], i);
	}
}
int main()
{
	std::ios::sync_with_stdio(false);
	is_prime();
	int t,n;
	cin >> t;
	while(t--)
	{
		cin >> n;
		if(ans[n]<INF)
			cout << ans[n] << endl;
		else cout << "-1" << endl;
		
	}
	
	
	return 0;
} 

 

I:直接按照题意模拟

#include<bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f;
string str[505];
int d[4][2]={{-1,0},{0,1},{1,0},{0,-1}},n,m;
int access(int x, int y)
{
	if(x<n&&y<m&&x>=0&&y>=0)
		return 1;
	return 0;
}
int main()
{
	std::ios::sync_with_stdio(false);
	int posi,xx,yy,i,flag;
	while(cin >> n >> m)
	{
		for(i = 0; i < n; i++)
			cin >> str[i];
		posi = 2;
		flag = 0;
		for(i = 0; i < m; i++)
		{
			posi = 2;
			xx = 0;
			yy = i;
			flag = 0;
			while(access(xx,yy)&&!flag)
			{
				while(access(xx,yy)&&str[xx][yy]=='.')
				{	
					xx=xx+d[posi][0];
					yy=yy+d[posi][1];
				}
//				cout << "tttt   " << xx << "   " << yy << endl;
				if(posi==2)
				{
					if(xx>n-1)
					{
						flag = 1;
						cout << (yy+1) << endl;
					}
				}
				if(flag) break;
				if(access(xx,yy)&&str[xx][yy]=='\\')
				{
					if(posi==0)
						posi=3;
					else if(posi==1)
						posi=2;
					else if(posi==2)
						posi=1;
					else if(posi==3)
						posi=0;
				}
				else if(access(xx,yy)&&str[xx][yy]=='/')
				{
					if(posi==0)
					{
//						cout << "0000000" << endl;
						posi=1;
					}
						
					else if(posi==1)
					{//cout << "1111111" << endl;
						posi=0;
					}
						
					else if(posi==2)
					{//cout << "2222222" << endl;
						posi=3;
					}
						
					else if(posi==3)
					{
//						cout << "333333" << endl;
						posi=2;
					}
						
				}
				xx=xx+d[posi][0];
				yy=yy+d[posi][1];
				
//				cout << xx << "    " << yy << endl;    
				if(posi==2)
				{
					if(xx>n-1)
					{
						flag = 1;
						cout << (yy+1) << endl;
					}
				}
				
 				if(flag) break;
			}
			if(!flag)cout << "-1" << endl;
			
		}
	}

	return 0;
} 

J :  把数字换成二进制,A , B 的每一位分别是(0,0)(1,0)(0,1) 是满足情况,所以是3^m;

#include<bits/stdc++.h>
using namespace std;
#define ll long long int
const int INF = 0x3f3f3f3f;
const int mod = 998244353;

ll qpow(ll a,ll b)
{
	ll res = 1;
	while(b){ 
		if(b%2!=0){  
			res *= a; res %= mod; 
		}  
		a *= a; a%=mod; b /= 2; 
	}
	return res;
}

int main()
{
	std::ios::sync_with_stdio(false);
	int m;
	while(cin >> m)
	{
		cout << qpow(3,m) << endl;;
	}

	return 0;
} 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值