某个contest几道解题报告

12 篇文章 0 订阅
10 篇文章 0 订阅

【前言】


  周六第一天跑到实验室复习。

  复习到一半看到有个contest。看了一题,觉得可以做,然后就YY了。

  然后一发就不可收拾了……

  确实是好久没做ACM了,最近都忙着大作业。


【题解】

首先看到第三题。由于那些题目是hdu没有的,所以只能把题目也copy过来了。

  由于每个数都很小,所以开个数组存一下就可以了。

  于是就把水题敲出来了。看来我水题帝的称号还是名副其实的啊。


小强与那个她的故事

Time Limit : 3000/1000ms (Java/Other)   Memory Limit : 65535/32768K (Java/Other)
Total Submission(s) : 16   Accepted Submission(s) : 9
Font: Times New Roman | Verdana | Georgia
Font Size:  

Problem Description

USTC一年一度的“美丽邂逅”都异常火爆,特别是今年传说中千年难遇的“千年光棍节”,当然这一活动,传说中的小强肯定要去凑热闹,“众里寻他千百度,蓦然回首,那人却在灯火阑珊处”,小强终于遇到了传说中的那个她,于是速度上前搭讪,可是那个她在小强还未来得及开口之前,就一眼认出了小强(有可能是因为长得太帅了吧) 。于是那个她竟然公开撒起了娇,“小强哥哥,找你找得好苦呀,我们算法课老师给了一个题,不会呀,我问了好多人,都不会,如果小强哥哥会的话。。。我。。。”。 小强听到这些话,顿时春心荡漾起来,不过他故作平静,很Man地说了句“说!”。于是那个她说出了困扰她很久的问题。 
有N个正整数,求出他们两两之差的绝对值之和。比如有如下4个数:
4 3 5 2,那么答案为:
|4-3|+|4-5|+|4-2|+|3-5|+|3-2|+|5-2|=10
这对小强来说,简直就是“一块蛋糕”。但是小强还有其他妹子要邂逅,所以将这个问题留给你来搞定了。

Input

第一行输入一个正整数T(T<=100),代表下面共有T组测试数据。每组测试数据包括两部分:
首先一个正整数N(1<=N<=100000),代表下面有N个正整数。
接下来输入N个正整数,每个正整数不大于200。

Output

输出相应的答案,答案可能会超过int范围,但是保证不会超过long long范围。

Sample Input

1
4
4 3 5 2

Sample Output

10

Author

gamegame151

【1003代码】

#include <iostream>
using namespace std;

#define LL __int64

int num[205];

int main()
{
	int t;
	int n, x, i, j;
	LL sum;
	scanf("%d", &t);
	while(t--)
	{
		scanf("%d", &n);
		memset(num, 0, sizeof(num));
		sum = 0;
		for (i=0; i<n; i++)
		{
			scanf("%d", &x);
			num[x]++;
		}
		for (i=1; i<=200; i++)
		{
			if (num[i]!=0)
			{
				for (j=i+1; j<=200; j++)
				{
					if (num[j]!=0)
					{
						sum += (LL)(j-i)*num[i]*num[j];
					}
				}
			}
		}
		printf("%I64d\n", sum);
	}
	return 0;
}


  然后发现1007是a+b问题,哎,直接copy代码。

  然后看到第二题。

生成函数之类的东东吧。自己功力不深,还没办法应用。

于是随便想。由于是等号。所以枚举5z,对于n-5z算出可以得到多少个2y,剩下的就是x了。

O(n)的复杂度就可以出解。后来发现确实是可以用生产函数来做,思路也是差不多这样,不过可能就显得更严谨一些。

W和方程的故事

Time Limit : 3000/1000ms (Java/Other)   Memory Limit : 65535/32768K (Java/Other)
Total Submission(s) : 3   Accepted Submission(s) : 2
Font: Times New Roman | Verdana | Georgia
Font Size:  

Problem Description

W最近在研究一个方程X+2Y+5Z=N,其中X,Y,Z是未知数,N是一个已知的整数且X,Y,Z,N都是非负整数。他想求出该方程共有多少组解,你能帮助他吗?

Input

第一行输入一个正整数T(T<=100),代表下面共有T组测试数据。下面T行,每行一个整数N(0<=N<=1000000)。

Output

输出该方程解的组数。

Sample Input

2
0
6

Sample Output

1
5

Author

gamegame151

【1002代码】

#include <iostream>
using namespace std;

int main()
{
	int i;
	int n, t;
	__int64 ct;
	scanf("%d", &t);
	while(t--)
	{
		scanf("%d", &n);
		ct = 0;
		for (i=0; i*5<=n; i++)
		{
			ct += (__int64)(n-i*5)/2+1;
		}
		printf("%I64d\n", ct);
	}
	return 0;
}

之后就打算继续去复习了。但是受不了ACM的诱惑,于是又回来做了。

这道题由于所给数的范围比较小,所以2^20内就可以解决。所以可以先打表。


异样的二进制

Time Limit : 3000/1000ms (Java/Other)   Memory Limit : 65535/32768K (Java/Other)
Total Submission(s) : 6   Accepted Submission(s) : 3
Font: Times New Roman | Verdana | Georgia
Font Size:  

Problem Description

话说LMM是USTC_ACM集训队为数不多的MM之一,当然每天慕名前来ym的人都很多,在风和日丽的今天,又来了三位。第一位是号称WA神的WA神,WA神是出了名的数学帝,送给了LMM一本微积分习题集,“oh,my god”,讨厌微积分的LMM果断木有给他ym的机会。第二位是号称物理帝的CBX大神,他同样也木有得到ym的机会,因为他竟然送了一本量子力学+量子化学的综合参考书给LMM,话说LMM讨厌死那些东西了。
第三位是号称WSN(Wo Shen Niu)的WSN帝,别看他名字很WS,可竟然获得了近距离ym LMM的机会,为什么呢? 很简单,因为他是“程序猿”。^-^
因为他知道LMM是CS专业的,对二进制转换非常熟悉,例如13的二进制为1101,因为13=1*2^3+1*2^2+0*2^1+1*2^0,所以他想证明他的魅力,带来了所谓的“负二进制”问题,将基数改为了-2,例如1101,实际上代表着:1*(-2)^3+1*(-2)^2+0*(-2)^2+1*(-2)^0=-3,所以-3的“负二进制”为1101.
同样作为“程序猿”的你,会这个问题么?如果会的说,说不定还能获得ym LMM的机会额,亲。
话说在科大要ym到一个妹纸,比进Final都还难呀。。。

Input

多组测试数据,每组输入一个数N(-100000<=N<=100000),代表着要转换的数。

Output

输出相应的转换结果。

Sample Input

-3
11

Sample Output

1101 
11111

Author

gamegame151

【1004代码】


#include <iostream>
using namespace std;

const int maxn = 100000;

struct node
{
	int len;
	bool by[30];
}num[2*maxn+5];

int value[30];

void dfs(int v, int m, node now, int cur)
{
	if (v==m)
	{
		if (cur<=maxn && cur>=-maxn && num[cur+maxn].len==0)
			memcpy(&num[cur+maxn], &now, sizeof(node));
		return;
	}
	now.len++;
	now.by[now.len-1] = false;
	dfs(v+1, m, now, cur);
	now.by[now.len-1] = true;
	cur += value[v];
	dfs(v+1, m, now, cur);
}

void show(int n)
{
	n += maxn;
	int i;
	for (i=num[n].len-1; i>=0; i--)
	{
		if (num[n].by[i]) break;
	}
	if (i<0) i=0;
	for ( ; i>=0; i--)
	{
		if (num[n].by[i]) printf("1");
		else printf("0");
	}
	printf("\n");
}

int main()
{
	int i;
	value[0] = 1;
	for (i=1; i<20; i++) value[i] = value[i-1]*(-2);
	for (i=-maxn; i<=maxn; i++) num[i+maxn].len = 0;
	node now;
	now.len = 0;
	dfs(0, 20, now, 0);
	int n;
	while(scanf("%d", &n)!=EOF)
	{
		show(n);
	}
	return 0;
}

看到1008有人很快出了,于是断定为规律题。开始找规律。

然后果真被我找到了。A掉。

三角形

Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 65536/32768K (Java/Other)
Total Submission(s) : 6   Accepted Submission(s) : 3
Font: Times New Roman | Verdana | Georgia
Font Size:  

Problem Description

用N个三角形最多可以把平面分成几个区域?

Input

输入数据的第一行是一个正整数T(1<=T<=10000),表示测试数据的数量.然后是T组测试数据,每组测试数据只包含一个正整数N(1<=N<=10000).

Output

对于每组测试数据,请输出题目中要求的结果.

Sample Input

2
1
2

Sample Output

2
8

Author

Ignatius.L

【1008代码】


#include <iostream>
using namespace std;

const int maxn = 10000;

int x[maxn+5];

int main()
{
	int i;
	x[1] = 2;
	for (i=2; i<=maxn; i++) x[i] = x[i-1] + 6*(i-1);
	int t, n;
	scanf("%d", &t);
	while(t--)
	{
		scanf("%d", &n);
		printf("%d\n", x[n]);
	}
	return 0;
}

然后决定动手虎视眈眈已久的1009。

只是一道简单的字典树,不过就是有点懒得打。

没想到居然8分钟就被我敲出来了。看来还是有点实力的。

统计难题

Time Limit : 4000/2000ms (Java/Other)   Memory Limit : 131070/65535K (Java/Other)
Total Submission(s) : 3   Accepted Submission(s) : 2
Font: Times New Roman | Verdana | Georgia
Font Size:  

Problem Description

Ignatius最近遇到一个难题,老师交给他很多单词(只有小写字母组成,不会有重复的单词出现),现在老师要他统计出以某个字符串为前缀的单词数量(单词本身也是自己的前缀).

Input

输入数据的第一部分是一张单词表,每行一个单词,单词的长度不超过10,它们代表的是老师交给Ignatius统计的单词,一个空行代表单词表的结束.第二部分是一连串的提问,每行一个提问,每个提问都是一个字符串.

注意:本题只有一组测试数据,处理到文件结束.

Output

对于每个提问,给出以该字符串为前缀的单词的数量.

Sample Input

banana
band
bee
absolute
acm

ba
b
band
abc

Sample Output

2
3
1
0

Author

Ignatius.L


【1009代码】


#include <iostream>
using namespace std;

struct node
{
	int ct;
	int next[26];
}tree[400000];

int tct;
int root;

int new_node()
{
	memset(&tree[tct], 0, sizeof(node));
	return tct++;
}

void insert(char *s)
{
	int rt = root;
	int i = 0;
	while(s[i]!='\0')
	{
		tree[rt].ct++;
		int tmp = s[i]-'a';
		if (tree[rt].next[tmp]==0)
			tree[rt].next[tmp] = new_node();
		rt = tree[rt].next[tmp];
		i++;
	}
	tree[rt].ct++;
}

int solve(char *s)
{
	int rt = root;
	int i = 0;
	while(s[i]!='\0')
	{
		int tmp = s[i]-'a';
		if (tree[rt].next[tmp]==0) return 0;
		rt = tree[rt].next[tmp];
		i++;
	}
	return tree[rt].ct;
}

int main()
{
	char str[20];
	tct = 0;
	root = new_node();
	while(gets(str))
	{
		if (str[0]=='\0') break;
		insert(str);
	}
	while(gets(str))
	{
		printf("%d\n", solve(str));
	}
	return 0;
}


最后剩下三道题没做。

第一题好像是线段树,前阵子看过,不过还没学到。

序列操作

Time Limit : 3000/1000ms (Java/Other)   Memory Limit : 65535/32768K (Java/Other)
Total Submission(s) : 0   Accepted Submission(s) : 0
Font: Times New Roman | Verdana | Georgia
Font Size:  

Problem Description

给你一个由N个正整数组成的序列,现在你可以对该序列进行如下两种操作:
Q L R:输出区间[L,R](1<=L,R<=N)中最长连续不下降子序列的长度。
C L R P:将区间[L,R] (1<=L,R<=N)中的每个整数都替换成整数P。
作为USTC的程序精英们,你能很顺利的解决这个问题么?

Input

第一行输入一个正整数T,代表下面有T组测试数据(T<=10)。
针对每组测试数据:
首先输入两个正整数N Q(1<=N<=100000,1<=Q<=100000),分别代表序列的长度和操作的次数。
接着输入N个正整数(每个正整数不大于1000)。
最后输入Q行,代表有Q次操作,每行有两种可能的形式:Q L R 或
C L R P。意义如上所示,其中P不大于1000。
注意: L有可能会大于R。

Output

针对每次Q L R操作,输出对应区间[L,R]中最长连续不下降子序列的长度。

Sample Input

1
6 5
1 2 3 4 5 6 
Q 1 6         
C 4 3 2
Q 1 3
C 4 5 3
Q 2 5

Sample Output

6
3
4

Author

gamegame151


第五道貌似可以用二分做,不过当时已经没时间了。

K_Star风波

Time Limit : 3000/1000ms (Java/Other)   Memory Limit : 65535/32768K (Java/Other)
Total Submission(s) : 0   Accepted Submission(s) : 0
Font: Times New Roman | Verdana | Georgia
Font Size:  

Problem Description

USTC的K_Star已成为USTC的标志性文化之一了,每年都会吸引很多俊男俏女前来参赛,当然今年也不例外。现在假设共有N名歌手和M名评委,歌手编号为1,2…,N,评委编号为1,2..M。歌手歌唱的时间分别为T1,T2,..,TN。评委们需要对歌手进行点评,且每名歌手需要且仅需要一名评委进行点评,每名评委至少要对一名歌手进行点评,且每一位评委只能对连续编号的某些歌手进行点评,点评时间为这些歌手唱歌时间之和。 
现在请你来设计一种点评方案,使得评委们的点评时间尽可能的短。评委们的点评时间定义为点评时间最多的那位评委所用掉的时间。
举个例子:假设有5个歌手,3个评委。歌手的歌唱时间依次为:4 5 3 1 2,那么可以这样进行点评: 4 /5 3 1/ 2 ,即第一位评委点评第一位歌手,用时4个单位;第二位评委点评第二,三,四位歌手,用时9个单位;第三位评委点评第五位歌手,用时2个单位;那么该方案的点评时间为9。
当然这并不是最优的方案,最优方案需要你用程序找出。

Input

第一行一个整数T(T<=100),代表共有T组测试数据。
每组测试数据包括两部分:
第一部分:N M 分别代表歌手数和评委数。(1<=M<=N<=500)
第二部分:N个正整数,分别代表歌手的歌唱时间(不大于2000的正整数)。

Output

输出包括M+1行,第一行为最短的点评时间。第i(2<=i<=M+1)行分别为第i-1位评委要点评歌手的起始编号和终止编号,如果有多组解,尽可能让前面的评委少点评。

Sample Input

1
5 3
4 5 3 1 2

Sample Output

6
1 1
2 2
3 5

Author

gamegame151

第六道是最大子矩阵的问题。不过有点变种,还没细想。

RG的故事

Time Limit : 3000/1000ms (Java/Other)   Memory Limit : 65535/32768K (Java/Other)
Total Submission(s) : 2   Accepted Submission(s) : 0
Font: Times New Roman | Verdana | Georgia
Font Size:  

Problem Description

相信大家都做过传说中“To the max”这题吧,大致描述如下:
给你一个全部由数字组成的大小为N*M的矩阵,该矩阵包含了若干个子矩阵,定义子矩阵的和为该子矩阵中所有数字之和,我们可以通过比较所有子矩阵,找出最大子矩阵的和。 
例如有如下一个矩阵:
  0 -2 -7 0 
  9 2 -6 2 
  -4 1 -4 1 
  -1 8 0 -2 
那么最大子矩阵和为15,对应子矩阵为:
  9 2 
  -4 1 
  -1 8 
相信大家都能快速求解出该问题。其实想一想,还可以求出满足子矩阵和最大的子矩阵的个数(如上例中只有1个子矩阵和为15且最大)。
亲,相信难不到你们的!!!

Input

第一行输入一个数T(T<=20),代表下面将有T组测试数据。每组测试数据包括两部分:
第一部分:两个正整数N,M (0<N,M<=100),分别矩阵的维数。
第二部分:一个N*M的数字矩阵,该矩阵中每个数字的范围为[-1000, 1000]。

Output

针对每组测试数据,输出最大子矩阵和、最大子矩阵的个数。用空格隔开。

Sample Input

1
2 3
0 0 0
0 0 0 

Sample Output

0 18

Author

gamegame151

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值