简单整理(nyoj 132 && 744 && tyvj 1001 && 1141 && 1170 && 1067 && 1015)

博主分享了自己在编程竞赛中遇到的一些题目,包括nyoj 132、744、tyvj 1001等,重点讨论了如何找到最长回文子串、素数相关问题的解决思路以及模拟和动态规划的应用。提醒读者面对素数问题时不要盲目使用素数拆选法,并表达了对于遗忘搜索题型的担忧。

实在没有脑细胞做新题,就整理整理旧题吧

nyoj 132:点击打开链

找最长回文子串,但是要求忽略空格和标点,然后将最大回文子串输出.

#include<stdio.h>
#include<string.h>
#include<ctype.h>

char buf[5005], res[5005], pri[5005]; //buf输入,res记录buf中字母并转换成大写,pri记录res中字母在buf中位置

int main()
{
	int N;
	scanf("%d", &N);
	getchar(); 
	while(N--)
	{
		int m = 0, len, max = 0;
		int i, j, x, y;
		gets(buf); 
		len = strlen(buf);
		
		for(i = 0; i < len; i ++)
		{
			if(isalpha(buf[i])) //判断是否是字母
			{
				pri[m] = i;
				res[m++] = toupper(buf[i]); //字母转换为大写
			}
		}
		
		for(i = 0; i < m; i ++) //枚举回文串的中间位置i,注意i是中心
		{
			for(j = 0; i - j >= 0 && i + j < m; j ++) //最长回文字串为奇数
			{//枚举回文串的长度 
				if(res[i - j] != res[i + j]) 
					break; //向两边扩展,不相等跳出
				if(j * 2 + 1 > max)
				{
					max = j * 2 + 1; //记录最长回文字串长度
					x = pri[i - j]; //记录最长回文字串起点
					y = pri[i + j]; //记录最长回文字串终点
				}
			}
			for(j = 0; i - j >= 0 && i + j < m; j ++) //最长回文字串为偶数
			{
				if(res[i - j] != res[i + j + 1]) 
					break;
				if(j * 2 + 2 > max)
				{
					max = j * 2 + 2;
					x = pri[i - j];
					y = pri[i + j + 1];
				}
			}
		}
		
		for(i = x; i <= y; i ++) //x,y为起点,终点
			printf("%c", buf[i]);
		printf("\n");
	}
	return 0;
}

nyoj744 : 点击打开链接

找规律.....都说是水题.....其实规律我没找到......

右边界的二进制位数为c,那么2的c次方减1就是最终答案......

#include<stdio.h>
#include <math.h>

int main()
{
	long long a, b;
	while(scanf("%lld %lld", &a, &b) != EOF)
	{
		int c = 0;
		b ^= a;
		while(b)
		{
			c ++;
			b >>= 1;
		}
		long long ans = 1;
		while(c)
		{
			ans *= 2;
			c --;
		}
		printf("%lld\n", ans - 1);
	}
}

tyvj 1001 : 点击打开链接

做这个题想写的就是,看到有关素数的题不要一上来就写素数拆选法,这题就根本用不到.....

#include <stdio.h>
#include <algorithm>
#define N 1000000
using namespace std;

int a[10010];
//bool prime[N];
//int p[1000000], k = 0;
/*
void isprime()
{
	int i, j;
	prime[0] = prime[1] = 1;
	for(i = 2; i < N; i++)
	{
		if(!prime[i])
		{
			p[k ++] = i;
			for(j = 0; j < k && i * p[j] < N; j ++)
			{
				prime[i * p[j]] = 1;
				if((i % p[j]) == 0)
					break;
			}
		}
	}
}
*/

int isprime(int x)
{
	if(x <= 1)
		return 0;
	int i;
	for(i = 2; i * i <= x; i++)
	{
		if(x % i == 0)
			return 0;
	}
	return 1;
}

int main(void)
{
	int n, k;
	//isprime();
	while(scanf("%d %d", &n, &k) != EOF)
	{
		int i;
		for(i = 0; i < n; i++)
			scanf("%d", &a[i]);
		sort(a, a + n);
		int x = a[n - k] - a[k - 1];
		if(!isprime(x))
			printf("NO\n");
		else
			printf("YES\n");
		printf("%d\n", x);
	}
	return 0;
}

tyvj1141: 点击打开链接

挺繁琐的一个模拟题, 注意cmp函数

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>

struct node
{
	char s[30];
};
node str[110];
int let[26];

int cmp(const void *a, const void *b)
{
	return (((node *)a)->s[0] > ((node *)b)->s[0] ? 1 : -1);
}

int main (void)
{
	int n = 0, i, j;
	while(1)
	{
		gets(&str[n].s[1]);
		if(str[n].s[1] == '-' && str[n].s[2] == '1')
			break;
		int temp = 0, i = 1;
		while(isdigit(str[n].s[i]))
		{
			temp = temp * 10 + (str[n].s[i] - 48);
			i ++;
		}
		str[n].s[0] = temp + 48;
		n ++;
	}
	int c = 0;
	qsort(str, n, sizeof(str[0]), cmp);
	
	char sta = str[0].s[0];
	while(1)
	{
		for(i = 0; i < n; i++)
			if(str[i].s[0] == sta)
				break;
		c ++;
		j = 0;
		while(str[i].s[j] != ' ')
			j ++;
		j++;
		if(str[i].s[j] == 'I' && str[i].s[j + 1] == 'F')
		{//处理if语句 
			j += 3;
			char temp = str[i].s[j];
			int temp2 = 0;
			j += 2;
			while(isdigit(str[i].s[j]))
			{
				temp2 = temp2 * 10 + (str[i].s[j] - 48);
				j ++;
			}
			if(let[temp - 'A'] == temp2)
			{
				j += 4;
				temp2 = 0;
				while(isdigit(str[i].s[j]))
				{
					temp2 = temp2 * 10 + (str[i].s[j] - 48);	
					j++;
				}
				sta = temp2 + 48;
				continue;
			}
			else
			{
				sta = str[i + 1].s[0];
				continue;
			}
		}
		if(str[i].s[j] == 'E' && str[i].s[j + 1] == 'N' && str[i].s[j + 2] == 'D')
			break;	
		if(str[i].s[j + 1] == '+')
		{//处理赋值语句 
			char temp = str[i].s[j];
			int temp2 = 0;
			j += 2;
			while(isdigit(str[i].s[j]))
			{
				temp2 = temp2 * 10 + (str[i].s[j] - 48);
				j ++;
			}
			let[temp - 'A'] += temp2;
			sta = str[i + 1].s[0];
			continue;
		}
		if(str[i].s[j + 1] == '?')
		{//处理输出语句 
			sta = str[i + 1].s[0];
			continue;
		}
		if(str[i].s[j] == 'G' && str[i].s[j + 1] == 'O')
		{//处理跳转语句 
			j += 3;
			int temp = 0;
			while(isdigit(str[i].s[j]))
			{
				temp = temp * 10 + (str[i].s[j] - 48);
				j ++;
			}
			sta = temp + 48;
			continue;
		} 
	}
	printf("%d\n", c);
	return 0;
}


tyvj 1170: 点击打开链接

搜索题,感觉快连搜索题都不会写了.......好慌啊

#include <stdio.h>

int count, n;
int a[40];

int f(int k)
{
	int i, j, l;
	for(i = 1; i <= (k + 1) / 3; i++)
	{
		int f = 1;
		for(l = 0; l < i; l ++)
		{
			if(a[k - l] != a[k - i - l] || a[k - i - l] != a[k - i - i - l])
			{//三个不相等 
				f = 0;//不存在长度为i的连续子串 
				break;
			}
		}
		if(f)//存在长度为i的连续的子串 
			return 0;
	}
	return 1;
} 

void dfs(int x)
{
	if(x == n)
	{	
		count++;
		return ;
	}
	a[x] = 0;
	if(f(x))
		dfs(x + 1);
	a[x] = 1;
	if(f(x))
		dfs(x + 1);
}

int main (void)
{
	while(scanf("%d", &n) != EOF)
	{
		count = 0;
		dfs(0);
		printf("%d\n", count);
	}
	return 0;
}

tyvj 1067: 点击打开链接

动归.其实就是最长递增子序列,两个数组,dp1[i]存放以第i个元素为结尾的最长递增子序列,dp2[i]存放以第i个元素为开头的最长递减子序列,然后每个位置对应这相加,取最大的就好.

#include <stdio.h>

int a[110];
int dp1[110], dp2[110];

int main (void)
{
	int n;
	while(scanf("%d", &n) != EOF)
	{
		int i, j;
		for(i = 0; i < n; i++)
			scanf("%d", &a[i]);
		for(i = 0; i < n; i++)
			dp1[i] = dp2[i] = 1;
		for(i = 0; i < n; i++)
		{
			for(j = i - 1; j >= 0; j--)
			{
				if(a[j] < a[i])	
					dp1[i] = dp1[i] > (dp1[j] + 1) ? dp1[i] : (dp1[j] + 1);
			}
		}
		for(i = n - 1; i >= 0; i--)
		{
			for(j = i + 1; j <= n; j++)
			{
				if(a[j] < a[i])
					dp2[i] = dp2[i] > (dp2[j] + 1) ? dp2[i] : (dp2[j] + 1);
			}
		}
		int max = -1;
		for(i = 0; i < n; i++)
		{
			if(dp1[i] + dp2[i] - 1 > max)
				max = dp1[i] + dp2[i] - 1;
		}	
		printf("%d\n", n - max);
	}
	return 0;
}

tyvj 1015:点击打开链接

完全背包求最小值,注意初始化。

#include <stdio.h>

int a[11];
int dp[110];

void init()
{
	int i;
	for(i = 0; i < 110; i++)
		dp[i] = 0x3f3f3f3f;
}

int main (void)
{
	int i, n, j;
	init();
	dp[0] = 0;
	for(i = 1; i <= 10; i++)
		scanf("%d", &a[i]);
	scanf("%d", &n);
	for(i = 1; i <= 10; i++)
		for(j = i; j <= n; j++)
			dp[j] = dp[j] < (dp[j - i] + a[i]) ? dp[j] : (dp[j - i] + a[i]);
	printf("%d\n", dp[n]);
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值