2.19(Virtual Judge)

文章介绍了几个编程题目,涉及字符串模式识别(如TripleMetre),数组排序与查找(Counting2、Neighbors*、Xdrawing),数值计算(Sumofdifference)、进制转换(Unlucky7)、组合数学(Stamp、DuodecimFerra)、卡片重组(ReorderCards)、字符映射(abc285_brutmhyhiizp)以及数组操作(ColorfulCandies、Triangles)。展示了作者对不同IT技术问题的解决方案和思考过程。
摘要由CSDN通过智能技术生成

目录

A.  Triple Metre

B.  Counting 2

C.  Neighbors *

D.  X drawing**

E.  Sum of difference/

F.  Unlucky 7/

G.  Stamp**

H.  Duodecim Ferra**

I.  Reorder Cards**

J.  abc285_brutmhyhiizp

K.  Colorful Candies/

L.  Triangles**


A.  Triple Metre

这道题就是看有没有字符串有没有按oxxoxx的规律连续下去,可能出现的情况就是以下4种:

1.字符串长度小于3,都满足;

2.字符串长度大于3,以o开头,就只可能是oxxoxx,以i计数,i%3==0时,a[i]=='o';

3.字符串长度大于3,以x开头,就可能是xoxxoxx,以i计数,(i+2)%3==0时,a[i]=='o';

4.字符串长度大于3,以x开头,还可能是xxoxxox,以i计数,(i+1)%3==0时,a[i]=='o';

#include<stdio.h>
#include<string.h>
int main()
{
	char a[1000001];
	scanf("%s", a);
	int k;
	k=strlen(a);
	if(a[0]=='o')
	{
		for(int i=1;i<k;i++)
		{
			if(i%3==0)
			{
				if(a[i]!='o')
				{
					printf("No");
					goto endc;
				}
			}
			else if(i%3!=0)
			{
				if(a[i]!='x')
				{
					printf("No");
					goto endc;
				}
			}
		}
		printf("Yes");
	}
	if(a[0]=='x')
	{
		if(k>1)
		{
			if(a[1]=='x')
			{
				for(int i=2;i<k;i++)
				{
					if((i+1)%3==0)
					{
						if(a[i]!='o')
						{
							printf("No");
							goto endc;
						}
					}
					else if((i+1)%3!=0)
					{
						if(a[i]!='x')
						{
							printf("No");
							goto endc;
						}
					}
				}
			}
			if(a[1]=='o')
			{
				for(int i=2;i<k;i++)
				{
					if((i+2)%3==0)
					{
						if(a[i]!='o')
						{
							printf("No");
							goto endc;
						}
					}
					else if((i+2)%3!=0)
					{
						if(a[i]!='x')
						{
							printf("No");
							goto endc;
						}
					}
				}
			}
		}
		printf("Yes");
	}
	endc:
	return 0;
}

B.  Counting 2

这道题就是去查找给出的x在原队列中排在什么位置,一开始我用常规的方法去查找,结果超时了。然后改用二分去查找,过了。

这个需要注意的点就是,当x在原队列中不存在时,即low>high时,第一个大于x的下标为n-low。

#include<stdio.h>
#include<algorithm>
using namespace std;
int main()
{
	int n, q, i, x, c, j;
	scanf("%d%d", &n, &q);
	int a[n];
	for(int i=0;i<n;i++)
	{
		scanf("%d", &a[i]);
	}
	sort(a, a+n);
	for(i=0;i<q;i++)
	{
		scanf("%d", &x);
		int low=0;
		int high=n-1;
		int mid=(low+high)/2;
		while (low<=high)
		{
			mid = (low+high)/2;
			if (a[mid]==x)
			{
				printf("%d\n", n-mid);
				break;
			}
			else if (a[mid]>x)
			{
				high=mid-1;
			}
			else 
			{
				low=mid+1;
			}
		}
		if (low>high)
			printf("%d\n", n-low);
	}
	return 0;
}

C.  Neighbors *

这道题就是排除掉No的情况,其他就是Yes,No有以下情况:

1.当一个人想站一起的人数大于2;

2.当一人想和另外两人站一起时,那两人想站一起;

3.当所有人站成一个环时;

#include <stdio.h>
#include <iostream>
#include <algorithm>
using namespace std;
const int N=1e5+10;
int d[N];
int f[N];
int p[N];
int find(int x);
int main()
{
	int n, m;
	scanf("%d%d", &n, &m);
	bool f=0;
	for (int i=1;i<=n;i++ )
		p[i]=i;
	for (int i=1;i<=m;i++ )
	{
		int a, b; cin >> a >> b;
		if (find(a)==find(b))
		{
			printf("No\n");
			goto end;
		}
		p[find(a)]=find(b);
		d[a]++;
		d[b]++;
	}
	for (int i=1;i<=n;i++ )
	{
		if (d[i]>2) 
		{
			printf("No\n");
			goto end;
		}
	}
	printf("Yes\n");
	end:
	return 0;
}
int find(int x)
{
	if (p[x]!=x)
	{
		p[x]=find(p[x]);
	}
	return p[x];
}

D.  X drawing**

E.  Sum of difference/

这道题我一开始就是想着去把每一个值都算出来,但写的时候就感觉会超时,结果真超时了。。。

然后我就发现其运算有一定的规律。

#include<cstdio>
#include<algorithm>
#include <iostream>
using namespace std;
long long a[1000000];
long long b[1000000];
int main()
{
	int n;
	scanf("%d", &n);
	for(int i=1;i<=n;i++)
	{
		scanf("%lld", &a[i]);
	}
	unsigned long long s=0;
	sort(a+1, a+n+1, greater<int>());
	for(int i=1;i<=n;i++)
	{
		b[i]=b[i-1]+a[i];
	}
	for(int i=1;i<=n;i++)
	{
		s+=b[n-i]-(b[n]-b[i]);
	}
	printf("%llu", s);
	return 0;
}

F.  Unlucky 7/

这道题就是先判断n是否含7,有则c++,没有则将n转换为8进制看它是否含7。

#include <stdio.h>
#include <iostream>
#include <string>
using namespace std;
int main()
{
	int n;
	scanf("%d", &n);
	char buf[10];
	int c=0;
	for (int i=1;i<=n;i++)
	{
		sprintf(buf, "%d", i);
		string s=string(buf);
		if (string::npos != s.find('7', 0))
		{
			c++;
		}
		else
		{
			sprintf(buf, "%o", i);
			s=string(buf);
			if (string::npos != s.find('7', 0))
			{
				c++;
			}
		}
	}
	printf("%d\n", n-c);
	return 0;
}

G.  Stamp**

H.  Duodecim Ferra**

这道题就是对于长度为L的铁棒,把它分成12段,就相当于从内部的L−1个点中挑选出11个不同的点进行切割。

#include<stdio.h>
int main()
{
	int n;
	scanf("%d", &n);
	long long p=1, c=0;
	for(int i=0; i<11; i++)
	{
		c=p*(n-(i+1))/(i+1);
		p=c;
	}
	printf("%lld\n", c);
	return 0;
}

I.  Reorder Cards**

这道题想要使用最少的数量覆盖尽可能大的区域,就需要使用尽可能长的邮票来覆盖,因为不能覆盖到蓝色方块,所以我们k的最大取值为夹在蓝色方块中的白色方块数量的最小值。又因为可以重复覆盖,所以对于一个长度为w的白色方块,我们只需要使用(w+k−1)/个邮票就可以。

#include<bits/stdc++.h>
using namespace std;
int main()
{
	int n,m;
	cin>>n>>m;
	vector<int> pos(m);
	for(int i=0;i<m;i++) 
		cin>>pos[i];
	pos.push_back(n+1);
	vector<int> cnt;
	sort(pos.begin(),pos.end());
	int pre=0;
	int mmin=(int)1e9;
	for(int i=0;i<(int)pos.size();i++)
	{
		int gap=pos[i]-pre-1;
		pre=pos[i];
		if(!gap) continue;
		mmin=min(mmin,gap);
		cnt.push_back(gap);
	}
	long long ans=0;
	for(int i=0;i<(int)cnt.size();i++)
		ans+=(cnt[i]+mmin-1)/mmin;
	cout<<ans;
	return 0;
}

J.  abc285_brutmhyhiizp

这道题就是读到a b c——x y z就分别返回对应的1 2 3——24 25 26,加到s上。每读取下一位字符,就将原本的s*26,因为每在下一位取一个字符,前面的一位都需要进过26次的重复,所以要乘26。

需要注意的是,这个s可能会很大,我是选择用unsigned long long来表示的。因为它可以存储到1*10的19次方大小。

#include<stdio.h>
#include<string.h>
int abspd(int i);
char a[15];
int main()
{
	unsigned long long s=0;
	scanf("%s", a);
	int k;
	k=strlen(a);
	int c;
	for(int i=0;i<k;i++)
	{
		s*=26;
		c=abspd(i);
		s+=c;
	}
	printf("%llu\n", s);
	return 0;
}
int abspd(int i)
{
	if(a[i]=='A')
		return 1;
	else if(a[i]=='B')
		return 2;
	else if(a[i]=='C')
		return 3;
	else if(a[i]=='D')
		return 4;
	else if(a[i]=='E')
		return 5;
	else if(a[i]=='F')
		return 6;
	else if(a[i]=='G')
		return 7;
	else if(a[i]=='H')
		return 8;
	else if(a[i]=='I')
		return 9;
	else if(a[i]=='J')
		return 10;
	else if(a[i]=='K')
		return 11;
	else if(a[i]=='L')
		return 12;
	else if(a[i]=='M')
		return 13;
	else if(a[i]=='N')
		return 14;
	else if(a[i]=='O')
		return 15;
	else if(a[i]=='P')
		return 16;
	else if(a[i]=='Q')
		return 17;
	else if(a[i]=='R')
		return 18;
	else if(a[i]=='S')
		return 19;
	else if(a[i]=='T')
		return 20;
	else if(a[i]=='U')
		return 21;
	else if(a[i]=='V')
		return 22;
	else if(a[i]=='W')
		return 23;
	else if(a[i]=='X')
		return 24;
	else if(a[i]=='Y')
		return 25;
	else if(a[i]=='Z')
		return 26;
}

K.  Colorful Candies/

这道题就是双指针,通过从左向右滑动窗口,来找到最大值。

#include<iostream>
#include<string>
#include<map>
using namespace std;
const int maxn = 3e5;
map<int,int> m; 
int nums[maxn+10];
int c[maxn+10];
int main()
{
	int n,k;
	cin>>n>>k;
	nums[n-k+1]=0;
	int cx=0;
	int maxx=0;
	for(int i=1;i<=n;i++)
	{
		cin>>c[i];
		if(i<=k)
		{
			if(m.count(c[i])==0)
			{
				m[c[i]]=1;
				cx++;
			}
			else
			{
				m[c[i]]++;
			}
		}
	}
	maxx=cx;
	for(int i=k+1;i<=n;i++)
	{
		m[c[i-k]]--;
		if(m[c[i-k]]==0)
		{
			cx--;
			m.erase(c[i-k]);
		}
		if(m.count(c[i])==0)
		{
			m[c[i]]=1;
			cx++;
			if(cx>maxx)
				maxx=cx;
		}
		else
		{
			m[c[i]]++;
		}
	}
	cout<<maxx<<endl;
	return 0;	
}

L.  Triangles**

这道题我没什么思路,但看到网上有很多种做法,比如:

首先排序。然后枚举最长的 2 根棍子 i,j(i<j),我们可以得到最短棍子的长度范围,即(l[i]+l[j],l[j]-l[i])。因此,我们可以进行二进制搜索来获得最短的棍子的数量。因为我们按顺序枚举,所以它们不会被重复计算;

对数组进行排序。在两个嵌套循环中,运行二进制搜索:lowerBound 和 upperBound 以查找可以形成有效三角形的第一个和最后一个索引。(这种我感觉好好写一点,但还是没写出来。。。)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值